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