OLD | NEW |
| (Empty) |
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 #ifdef WEBRTC_ANDROID | |
31 #include "talk/app/webrtc/test/androidtestinitializer.h" | |
32 #endif | |
33 #include "webrtc/base/gunit.h" | |
34 #include "webrtc/base/logging.h" | |
35 #include "webrtc/base/ssladapter.h" | |
36 #include "webrtc/base/sslstreamadapter.h" | |
37 #include "webrtc/base/stringencode.h" | |
38 #include "webrtc/base/stringutils.h" | |
39 | |
40 #define MAYBE_SKIP_TEST(feature) \ | |
41 if (!(feature())) { \ | |
42 LOG(LS_INFO) << "Feature disabled... skipping"; \ | |
43 return; \ | |
44 } | |
45 | |
46 using webrtc::DataChannelInterface; | |
47 using webrtc::FakeConstraints; | |
48 using webrtc::MediaConstraintsInterface; | |
49 using webrtc::MediaStreamInterface; | |
50 using webrtc::PeerConnectionInterface; | |
51 | |
52 namespace { | |
53 | |
54 const size_t kMaxWait = 10000; | |
55 | |
56 } // namespace | |
57 | |
58 class PeerConnectionEndToEndTest | |
59 : public sigslot::has_slots<>, | |
60 public testing::Test { | |
61 public: | |
62 typedef std::vector<rtc::scoped_refptr<DataChannelInterface> > | |
63 DataChannelList; | |
64 | |
65 PeerConnectionEndToEndTest() | |
66 : caller_(new rtc::RefCountedObject<PeerConnectionTestWrapper>( | |
67 "caller")), | |
68 callee_(new rtc::RefCountedObject<PeerConnectionTestWrapper>( | |
69 "callee")) { | |
70 #ifdef WEBRTC_ANDROID | |
71 webrtc::InitializeAndroidObjects(); | |
72 #endif | |
73 } | |
74 | |
75 void CreatePcs() { | |
76 CreatePcs(NULL); | |
77 } | |
78 | |
79 void CreatePcs(const MediaConstraintsInterface* pc_constraints) { | |
80 EXPECT_TRUE(caller_->CreatePc(pc_constraints)); | |
81 EXPECT_TRUE(callee_->CreatePc(pc_constraints)); | |
82 PeerConnectionTestWrapper::Connect(caller_.get(), callee_.get()); | |
83 | |
84 caller_->SignalOnDataChannel.connect( | |
85 this, &PeerConnectionEndToEndTest::OnCallerAddedDataChanel); | |
86 callee_->SignalOnDataChannel.connect( | |
87 this, &PeerConnectionEndToEndTest::OnCalleeAddedDataChannel); | |
88 } | |
89 | |
90 void GetAndAddUserMedia() { | |
91 FakeConstraints audio_constraints; | |
92 FakeConstraints video_constraints; | |
93 GetAndAddUserMedia(true, audio_constraints, true, video_constraints); | |
94 } | |
95 | |
96 void GetAndAddUserMedia(bool audio, FakeConstraints audio_constraints, | |
97 bool video, FakeConstraints video_constraints) { | |
98 caller_->GetAndAddUserMedia(audio, audio_constraints, | |
99 video, video_constraints); | |
100 callee_->GetAndAddUserMedia(audio, audio_constraints, | |
101 video, video_constraints); | |
102 } | |
103 | |
104 void Negotiate() { | |
105 caller_->CreateOffer(NULL); | |
106 } | |
107 | |
108 void WaitForCallEstablished() { | |
109 caller_->WaitForCallEstablished(); | |
110 callee_->WaitForCallEstablished(); | |
111 } | |
112 | |
113 void WaitForConnection() { | |
114 caller_->WaitForConnection(); | |
115 callee_->WaitForConnection(); | |
116 } | |
117 | |
118 void OnCallerAddedDataChanel(DataChannelInterface* dc) { | |
119 caller_signaled_data_channels_.push_back(dc); | |
120 } | |
121 | |
122 void OnCalleeAddedDataChannel(DataChannelInterface* dc) { | |
123 callee_signaled_data_channels_.push_back(dc); | |
124 } | |
125 | |
126 // Tests that |dc1| and |dc2| can send to and receive from each other. | |
127 void TestDataChannelSendAndReceive( | |
128 DataChannelInterface* dc1, DataChannelInterface* dc2) { | |
129 rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc1_observer( | |
130 new webrtc::MockDataChannelObserver(dc1)); | |
131 | |
132 rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc2_observer( | |
133 new webrtc::MockDataChannelObserver(dc2)); | |
134 | |
135 static const std::string kDummyData = "abcdefg"; | |
136 webrtc::DataBuffer buffer(kDummyData); | |
137 EXPECT_TRUE(dc1->Send(buffer)); | |
138 EXPECT_EQ_WAIT(kDummyData, dc2_observer->last_message(), kMaxWait); | |
139 | |
140 EXPECT_TRUE(dc2->Send(buffer)); | |
141 EXPECT_EQ_WAIT(kDummyData, dc1_observer->last_message(), kMaxWait); | |
142 | |
143 EXPECT_EQ(1U, dc1_observer->received_message_count()); | |
144 EXPECT_EQ(1U, dc2_observer->received_message_count()); | |
145 } | |
146 | |
147 void WaitForDataChannelsToOpen(DataChannelInterface* local_dc, | |
148 const DataChannelList& remote_dc_list, | |
149 size_t remote_dc_index) { | |
150 EXPECT_EQ_WAIT(DataChannelInterface::kOpen, local_dc->state(), kMaxWait); | |
151 | |
152 EXPECT_TRUE_WAIT(remote_dc_list.size() > remote_dc_index, kMaxWait); | |
153 EXPECT_EQ_WAIT(DataChannelInterface::kOpen, | |
154 remote_dc_list[remote_dc_index]->state(), | |
155 kMaxWait); | |
156 EXPECT_EQ(local_dc->id(), remote_dc_list[remote_dc_index]->id()); | |
157 } | |
158 | |
159 void CloseDataChannels(DataChannelInterface* local_dc, | |
160 const DataChannelList& remote_dc_list, | |
161 size_t remote_dc_index) { | |
162 local_dc->Close(); | |
163 EXPECT_EQ_WAIT(DataChannelInterface::kClosed, local_dc->state(), kMaxWait); | |
164 EXPECT_EQ_WAIT(DataChannelInterface::kClosed, | |
165 remote_dc_list[remote_dc_index]->state(), | |
166 kMaxWait); | |
167 } | |
168 | |
169 protected: | |
170 rtc::scoped_refptr<PeerConnectionTestWrapper> caller_; | |
171 rtc::scoped_refptr<PeerConnectionTestWrapper> callee_; | |
172 DataChannelList caller_signaled_data_channels_; | |
173 DataChannelList callee_signaled_data_channels_; | |
174 }; | |
175 | |
176 // Disabled for TSan v2, see | |
177 // https://bugs.chromium.org/p/webrtc/issues/detail?id=4719 for details. | |
178 // Disabled for Mac, see | |
179 // https://bugs.chromium.org/p/webrtc/issues/detail?id=5231 for details. | |
180 #if !defined(THREAD_SANITIZER) && !defined(WEBRTC_MAC) | |
181 TEST_F(PeerConnectionEndToEndTest, Call) { | |
182 CreatePcs(); | |
183 GetAndAddUserMedia(); | |
184 Negotiate(); | |
185 WaitForCallEstablished(); | |
186 } | |
187 #endif // if !defined(THREAD_SANITIZER) && !defined(WEBRTC_MAC) | |
188 | |
189 TEST_F(PeerConnectionEndToEndTest, CallWithLegacySdp) { | |
190 FakeConstraints pc_constraints; | |
191 pc_constraints.AddMandatory(MediaConstraintsInterface::kEnableDtlsSrtp, | |
192 false); | |
193 CreatePcs(&pc_constraints); | |
194 GetAndAddUserMedia(); | |
195 Negotiate(); | |
196 WaitForCallEstablished(); | |
197 } | |
198 | |
199 // Verifies that a DataChannel created before the negotiation can transition to | |
200 // "OPEN" and transfer data. | |
201 TEST_F(PeerConnectionEndToEndTest, CreateDataChannelBeforeNegotiate) { | |
202 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); | |
203 | |
204 CreatePcs(); | |
205 | |
206 webrtc::DataChannelInit init; | |
207 rtc::scoped_refptr<DataChannelInterface> caller_dc( | |
208 caller_->CreateDataChannel("data", init)); | |
209 rtc::scoped_refptr<DataChannelInterface> callee_dc( | |
210 callee_->CreateDataChannel("data", init)); | |
211 | |
212 Negotiate(); | |
213 WaitForConnection(); | |
214 | |
215 WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 0); | |
216 WaitForDataChannelsToOpen(callee_dc, caller_signaled_data_channels_, 0); | |
217 | |
218 TestDataChannelSendAndReceive(caller_dc, callee_signaled_data_channels_[0]); | |
219 TestDataChannelSendAndReceive(callee_dc, caller_signaled_data_channels_[0]); | |
220 | |
221 CloseDataChannels(caller_dc, callee_signaled_data_channels_, 0); | |
222 CloseDataChannels(callee_dc, caller_signaled_data_channels_, 0); | |
223 } | |
224 | |
225 // Verifies that a DataChannel created after the negotiation can transition to | |
226 // "OPEN" and transfer data. | |
227 #if defined(MEMORY_SANITIZER) | |
228 // Fails under MemorySanitizer: | |
229 // See https://code.google.com/p/webrtc/issues/detail?id=3980. | |
230 #define MAYBE_CreateDataChannelAfterNegotiate DISABLED_CreateDataChannelAfterNeg
otiate | |
231 #else | |
232 #define MAYBE_CreateDataChannelAfterNegotiate CreateDataChannelAfterNegotiate | |
233 #endif | |
234 TEST_F(PeerConnectionEndToEndTest, MAYBE_CreateDataChannelAfterNegotiate) { | |
235 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); | |
236 | |
237 CreatePcs(); | |
238 | |
239 webrtc::DataChannelInit init; | |
240 | |
241 // This DataChannel is for creating the data content in the negotiation. | |
242 rtc::scoped_refptr<DataChannelInterface> dummy( | |
243 caller_->CreateDataChannel("data", init)); | |
244 Negotiate(); | |
245 WaitForConnection(); | |
246 | |
247 // Creates new DataChannels after the negotiation and verifies their states. | |
248 rtc::scoped_refptr<DataChannelInterface> caller_dc( | |
249 caller_->CreateDataChannel("hello", init)); | |
250 rtc::scoped_refptr<DataChannelInterface> callee_dc( | |
251 callee_->CreateDataChannel("hello", init)); | |
252 | |
253 WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 1); | |
254 WaitForDataChannelsToOpen(callee_dc, caller_signaled_data_channels_, 0); | |
255 | |
256 TestDataChannelSendAndReceive(caller_dc, callee_signaled_data_channels_[1]); | |
257 TestDataChannelSendAndReceive(callee_dc, caller_signaled_data_channels_[0]); | |
258 | |
259 CloseDataChannels(caller_dc, callee_signaled_data_channels_, 1); | |
260 CloseDataChannels(callee_dc, caller_signaled_data_channels_, 0); | |
261 } | |
262 | |
263 // Verifies that DataChannel IDs are even/odd based on the DTLS roles. | |
264 TEST_F(PeerConnectionEndToEndTest, DataChannelIdAssignment) { | |
265 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); | |
266 | |
267 CreatePcs(); | |
268 | |
269 webrtc::DataChannelInit init; | |
270 rtc::scoped_refptr<DataChannelInterface> caller_dc_1( | |
271 caller_->CreateDataChannel("data", init)); | |
272 rtc::scoped_refptr<DataChannelInterface> callee_dc_1( | |
273 callee_->CreateDataChannel("data", init)); | |
274 | |
275 Negotiate(); | |
276 WaitForConnection(); | |
277 | |
278 EXPECT_EQ(1U, caller_dc_1->id() % 2); | |
279 EXPECT_EQ(0U, callee_dc_1->id() % 2); | |
280 | |
281 rtc::scoped_refptr<DataChannelInterface> caller_dc_2( | |
282 caller_->CreateDataChannel("data", init)); | |
283 rtc::scoped_refptr<DataChannelInterface> callee_dc_2( | |
284 callee_->CreateDataChannel("data", init)); | |
285 | |
286 EXPECT_EQ(1U, caller_dc_2->id() % 2); | |
287 EXPECT_EQ(0U, callee_dc_2->id() % 2); | |
288 } | |
289 | |
290 // Verifies that the message is received by the right remote DataChannel when | |
291 // there are multiple DataChannels. | |
292 TEST_F(PeerConnectionEndToEndTest, | |
293 MessageTransferBetweenTwoPairsOfDataChannels) { | |
294 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); | |
295 | |
296 CreatePcs(); | |
297 | |
298 webrtc::DataChannelInit init; | |
299 | |
300 rtc::scoped_refptr<DataChannelInterface> caller_dc_1( | |
301 caller_->CreateDataChannel("data", init)); | |
302 rtc::scoped_refptr<DataChannelInterface> caller_dc_2( | |
303 caller_->CreateDataChannel("data", init)); | |
304 | |
305 Negotiate(); | |
306 WaitForConnection(); | |
307 WaitForDataChannelsToOpen(caller_dc_1, callee_signaled_data_channels_, 0); | |
308 WaitForDataChannelsToOpen(caller_dc_2, callee_signaled_data_channels_, 1); | |
309 | |
310 rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc_1_observer( | |
311 new webrtc::MockDataChannelObserver(callee_signaled_data_channels_[0])); | |
312 | |
313 rtc::scoped_ptr<webrtc::MockDataChannelObserver> dc_2_observer( | |
314 new webrtc::MockDataChannelObserver(callee_signaled_data_channels_[1])); | |
315 | |
316 const std::string message_1 = "hello 1"; | |
317 const std::string message_2 = "hello 2"; | |
318 | |
319 caller_dc_1->Send(webrtc::DataBuffer(message_1)); | |
320 EXPECT_EQ_WAIT(message_1, dc_1_observer->last_message(), kMaxWait); | |
321 | |
322 caller_dc_2->Send(webrtc::DataBuffer(message_2)); | |
323 EXPECT_EQ_WAIT(message_2, dc_2_observer->last_message(), kMaxWait); | |
324 | |
325 EXPECT_EQ(1U, dc_1_observer->received_message_count()); | |
326 EXPECT_EQ(1U, dc_2_observer->received_message_count()); | |
327 } | |
328 | |
329 // Verifies that a DataChannel added from an OPEN message functions after | |
330 // a channel has been previously closed (webrtc issue 3778). | |
331 // This previously failed because the new channel re-uses the ID of the closed | |
332 // channel, and the closed channel was incorrectly still assigned to the id. | |
333 // TODO(deadbeef): This is disabled because there's currently a race condition | |
334 // caused by the fact that a data channel signals that it's closed before it | |
335 // really is. Re-enable this test once that's fixed. | |
336 TEST_F(PeerConnectionEndToEndTest, | |
337 DISABLED_DataChannelFromOpenWorksAfterClose) { | |
338 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); | |
339 | |
340 CreatePcs(); | |
341 | |
342 webrtc::DataChannelInit init; | |
343 rtc::scoped_refptr<DataChannelInterface> caller_dc( | |
344 caller_->CreateDataChannel("data", init)); | |
345 | |
346 Negotiate(); | |
347 WaitForConnection(); | |
348 | |
349 WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 0); | |
350 CloseDataChannels(caller_dc, callee_signaled_data_channels_, 0); | |
351 | |
352 // Create a new channel and ensure it works after closing the previous one. | |
353 caller_dc = caller_->CreateDataChannel("data2", init); | |
354 | |
355 WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 1); | |
356 TestDataChannelSendAndReceive(caller_dc, callee_signaled_data_channels_[1]); | |
357 | |
358 CloseDataChannels(caller_dc, callee_signaled_data_channels_, 1); | |
359 } | |
360 | |
361 // This tests that if a data channel is closed remotely while not referenced | |
362 // by the application (meaning only the PeerConnection contributes to its | |
363 // reference count), no memory access violation will occur. | |
364 // See: https://code.google.com/p/chromium/issues/detail?id=565048 | |
365 TEST_F(PeerConnectionEndToEndTest, CloseDataChannelRemotelyWhileNotReferenced) { | |
366 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); | |
367 | |
368 CreatePcs(); | |
369 | |
370 webrtc::DataChannelInit init; | |
371 rtc::scoped_refptr<DataChannelInterface> caller_dc( | |
372 caller_->CreateDataChannel("data", init)); | |
373 | |
374 Negotiate(); | |
375 WaitForConnection(); | |
376 | |
377 WaitForDataChannelsToOpen(caller_dc, callee_signaled_data_channels_, 0); | |
378 // This removes the reference to the remote data channel that we hold. | |
379 callee_signaled_data_channels_.clear(); | |
380 caller_dc->Close(); | |
381 EXPECT_EQ_WAIT(DataChannelInterface::kClosed, caller_dc->state(), kMaxWait); | |
382 | |
383 // Wait for a bit longer so the remote data channel will receive the | |
384 // close message and be destroyed. | |
385 rtc::Thread::Current()->ProcessMessages(100); | |
386 } | |
OLD | NEW |