OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include <map> | |
12 | |
13 #include "webrtc/base/fakesslidentity.h" | |
14 #include "webrtc/base/gunit.h" | |
15 #include "webrtc/base/helpers.h" | |
16 #include "webrtc/base/scoped_ptr.h" | |
17 #include "webrtc/base/sslidentity.h" | |
18 #include "webrtc/base/thread.h" | |
19 #include "webrtc/p2p/base/dtlstransportchannel.h" | |
20 #include "webrtc/p2p/base/faketransportcontroller.h" | |
21 #include "webrtc/p2p/base/p2ptransportchannel.h" | |
22 #include "webrtc/p2p/base/portallocator.h" | |
23 #include "webrtc/p2p/base/transportcontroller.h" | |
24 #include "webrtc/p2p/client/fakeportallocator.h" | |
25 | |
26 static const int kTimeout = 100; | |
27 static const char kIceUfrag1[] = "TESTICEUFRAG0001"; | |
28 static const char kIcePwd1[] = "TESTICEPWD00000000000001"; | |
29 static const char kIceUfrag2[] = "TESTICEUFRAG0002"; | |
30 static const char kIcePwd2[] = "TESTICEPWD00000000000002"; | |
31 | |
32 using cricket::Candidate; | |
33 using cricket::Candidates; | |
34 using cricket::FakeTransportChannel; | |
35 using cricket::FakeTransportController; | |
36 using cricket::IceConnectionState; | |
37 using cricket::IceGatheringState; | |
38 using cricket::TransportChannel; | |
39 using cricket::TransportController; | |
40 using cricket::TransportDescription; | |
41 using cricket::TransportStats; | |
42 | |
43 // Only subclassing from FakeTransportController because currently that's the | |
44 // only way to have a TransportController with fake TransportChannels. | |
45 // | |
46 // TODO(deadbeef): Change this once the Transport/TransportChannel class | |
47 // heirarchy is cleaned up, and we can pass a "TransportChannelFactory" or | |
48 // something similar into TransportController. | |
49 typedef FakeTransportController TransportControllerForTest; | |
50 | |
51 class TransportControllerTest : public testing::Test, | |
52 public sigslot::has_slots<> { | |
53 public: | |
54 TransportControllerTest() | |
55 : transport_controller_(new TransportControllerForTest()), | |
56 signaling_thread_(rtc::Thread::Current()) { | |
57 ConnectTransportControllerSignals(); | |
58 } | |
59 | |
60 void CreateTransportControllerWithWorkerThread() { | |
61 if (!worker_thread_) { | |
62 worker_thread_.reset(new rtc::Thread()); | |
63 worker_thread_->Start(); | |
64 } | |
65 transport_controller_.reset( | |
66 new TransportControllerForTest(worker_thread_.get())); | |
67 ConnectTransportControllerSignals(); | |
68 } | |
69 | |
70 void ConnectTransportControllerSignals() { | |
71 transport_controller_->SignalConnectionState.connect( | |
72 this, &TransportControllerTest::OnConnectionState); | |
73 transport_controller_->SignalReceiving.connect( | |
74 this, &TransportControllerTest::OnReceiving); | |
75 transport_controller_->SignalGatheringState.connect( | |
76 this, &TransportControllerTest::OnGatheringState); | |
77 transport_controller_->SignalCandidatesGathered.connect( | |
78 this, &TransportControllerTest::OnCandidatesGathered); | |
79 } | |
80 | |
81 FakeTransportChannel* CreateChannel(const std::string& content, | |
82 int component) { | |
83 TransportChannel* channel = | |
84 transport_controller_->CreateTransportChannel_w(content, component); | |
85 return static_cast<FakeTransportChannel*>(channel); | |
86 } | |
87 | |
88 void DestroyChannel(const std::string& content, int component) { | |
89 transport_controller_->DestroyTransportChannel_w(content, component); | |
90 } | |
91 | |
92 Candidate CreateCandidate(int component) { | |
93 Candidate c; | |
94 c.set_address(rtc::SocketAddress("192.168.1.1", 8000)); | |
95 c.set_component(1); | |
96 c.set_protocol(cricket::UDP_PROTOCOL_NAME); | |
97 c.set_priority(1); | |
98 return c; | |
99 } | |
100 | |
101 // Used for thread hopping test. | |
102 void CreateChannelsAndCompleteConnectionOnWorkerThread() { | |
103 worker_thread_->Invoke<void>(rtc::Bind( | |
104 &TransportControllerTest::CreateChannelsAndCompleteConnection_w, this)); | |
105 } | |
106 | |
107 void CreateChannelsAndCompleteConnection_w() { | |
108 transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLING); | |
109 FakeTransportChannel* channel1 = CreateChannel("audio", 1); | |
110 ASSERT_NE(nullptr, channel1); | |
111 FakeTransportChannel* channel2 = CreateChannel("video", 1); | |
112 ASSERT_NE(nullptr, channel2); | |
113 | |
114 TransportDescription local_desc( | |
115 std::vector<std::string>(), kIceUfrag1, kIcePwd1, cricket::ICEMODE_FULL, | |
116 cricket::CONNECTIONROLE_ACTPASS, nullptr, Candidates()); | |
117 std::string err; | |
118 transport_controller_->SetLocalTransportDescription( | |
119 "audio", local_desc, cricket::CA_OFFER, &err); | |
120 transport_controller_->SetLocalTransportDescription( | |
121 "video", local_desc, cricket::CA_OFFER, &err); | |
122 channel1->SignalCandidateGathered(channel1, CreateCandidate(1)); | |
123 channel2->SignalCandidateGathered(channel2, CreateCandidate(1)); | |
124 channel1->SetCandidatesGatheringComplete(); | |
125 channel2->SetCandidatesGatheringComplete(); | |
126 channel1->SetConnectionCount(2); | |
127 channel2->SetConnectionCount(2); | |
128 channel1->SetReceiving(true); | |
129 channel2->SetReceiving(true); | |
130 channel1->SetWritable(true); | |
131 channel2->SetWritable(true); | |
132 channel1->SetConnectionCount(1); | |
133 channel2->SetConnectionCount(1); | |
134 } | |
135 | |
136 protected: | |
137 void OnConnectionState(IceConnectionState state) { | |
138 if (!signaling_thread_->IsCurrent()) { | |
139 signaled_on_non_signaling_thread_ = true; | |
140 } | |
141 connection_state_ = state; | |
142 ++connection_state_signal_count_; | |
143 } | |
144 | |
145 void OnReceiving(bool receiving) { | |
146 if (!signaling_thread_->IsCurrent()) { | |
147 signaled_on_non_signaling_thread_ = true; | |
148 } | |
149 receiving_ = receiving; | |
150 ++receiving_signal_count_; | |
151 } | |
152 | |
153 void OnGatheringState(IceGatheringState state) { | |
154 if (!signaling_thread_->IsCurrent()) { | |
155 signaled_on_non_signaling_thread_ = true; | |
156 } | |
157 gathering_state_ = state; | |
158 ++gathering_state_signal_count_; | |
159 } | |
160 | |
161 void OnCandidatesGathered(const std::string& transport_name, | |
162 const Candidates& candidates) { | |
163 if (!signaling_thread_->IsCurrent()) { | |
164 signaled_on_non_signaling_thread_ = true; | |
165 } | |
166 candidates_[transport_name].insert(candidates_[transport_name].end(), | |
167 candidates.begin(), candidates.end()); | |
168 ++candidates_signal_count_; | |
169 } | |
170 | |
171 rtc::scoped_ptr<rtc::Thread> worker_thread_; // Not used for most tests. | |
172 rtc::scoped_ptr<TransportControllerForTest> transport_controller_; | |
173 | |
174 // Information received from signals from transport controller. | |
175 IceConnectionState connection_state_ = cricket::kIceConnectionConnecting; | |
176 bool receiving_ = false; | |
177 IceGatheringState gathering_state_ = cricket::kIceGatheringNew; | |
178 // transport_name => candidates | |
179 std::map<std::string, Candidates> candidates_; | |
180 // Counts of each signal emitted. | |
181 int connection_state_signal_count_ = 0; | |
182 int receiving_signal_count_ = 0; | |
183 int gathering_state_signal_count_ = 0; | |
184 int candidates_signal_count_ = 0; | |
185 | |
186 // Used to make sure signals only come on signaling thread. | |
187 rtc::Thread* const signaling_thread_ = nullptr; | |
188 bool signaled_on_non_signaling_thread_ = false; | |
189 }; | |
190 | |
191 TEST_F(TransportControllerTest, TestSetIceReceivingTimeout) { | |
192 FakeTransportChannel* channel1 = CreateChannel("audio", 1); | |
193 ASSERT_NE(nullptr, channel1); | |
194 | |
195 transport_controller_->SetIceConnectionReceivingTimeout(1000); | |
196 EXPECT_EQ(1000, channel1->receiving_timeout()); | |
197 | |
198 // Test that value stored in controller is applied to new channels. | |
199 FakeTransportChannel* channel2 = CreateChannel("video", 1); | |
200 ASSERT_NE(nullptr, channel2); | |
201 EXPECT_EQ(1000, channel2->receiving_timeout()); | |
202 } | |
203 | |
204 TEST_F(TransportControllerTest, TestSetSslMaxProtocolVersion) { | |
205 EXPECT_TRUE(transport_controller_->SetSslMaxProtocolVersion( | |
206 rtc::SSL_PROTOCOL_DTLS_12)); | |
207 FakeTransportChannel* channel = CreateChannel("audio", 1); | |
208 | |
209 ASSERT_NE(nullptr, channel); | |
210 EXPECT_EQ(rtc::SSL_PROTOCOL_DTLS_12, channel->ssl_max_protocol_version()); | |
211 | |
212 // Setting max version after transport is created should fail. | |
213 EXPECT_FALSE(transport_controller_->SetSslMaxProtocolVersion( | |
214 rtc::SSL_PROTOCOL_DTLS_10)); | |
215 } | |
216 | |
217 TEST_F(TransportControllerTest, TestSetIceRole) { | |
218 FakeTransportChannel* channel1 = CreateChannel("audio", 1); | |
219 ASSERT_NE(nullptr, channel1); | |
220 | |
221 transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLING); | |
222 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel1->GetIceRole()); | |
223 transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLED); | |
224 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, channel1->GetIceRole()); | |
225 | |
226 // Test that value stored in controller is applied to new channels. | |
227 FakeTransportChannel* channel2 = CreateChannel("video", 1); | |
228 ASSERT_NE(nullptr, channel2); | |
229 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, channel2->GetIceRole()); | |
230 } | |
231 | |
232 // Test that when one channel encounters a role conflict, the ICE role is | |
233 // swapped on every channel. | |
234 TEST_F(TransportControllerTest, TestIceRoleConflict) { | |
235 FakeTransportChannel* channel1 = CreateChannel("audio", 1); | |
236 ASSERT_NE(nullptr, channel1); | |
237 FakeTransportChannel* channel2 = CreateChannel("video", 1); | |
238 ASSERT_NE(nullptr, channel2); | |
239 | |
240 transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLING); | |
241 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel1->GetIceRole()); | |
242 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel2->GetIceRole()); | |
243 | |
244 channel1->SignalRoleConflict(channel1); | |
245 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, channel1->GetIceRole()); | |
246 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, channel2->GetIceRole()); | |
247 } | |
248 | |
249 TEST_F(TransportControllerTest, TestGetSslRole) { | |
250 FakeTransportChannel* channel = CreateChannel("audio", 1); | |
251 ASSERT_NE(nullptr, channel); | |
252 ASSERT_TRUE(channel->SetSslRole(rtc::SSL_CLIENT)); | |
253 rtc::SSLRole role; | |
254 EXPECT_TRUE(transport_controller_->GetSslRole(&role)); | |
255 EXPECT_EQ(rtc::SSL_CLIENT, role); | |
256 } | |
257 | |
258 TEST_F(TransportControllerTest, TestSetAndGetLocalCertificate) { | |
259 rtc::scoped_refptr<rtc::RTCCertificate> certificate1 = | |
260 rtc::RTCCertificate::Create( | |
261 rtc::scoped_ptr<rtc::SSLIdentity>( | |
262 rtc::SSLIdentity::Generate("session1", rtc::KT_DEFAULT)) | |
263 .Pass()); | |
264 rtc::scoped_refptr<rtc::RTCCertificate> certificate2 = | |
265 rtc::RTCCertificate::Create( | |
266 rtc::scoped_ptr<rtc::SSLIdentity>( | |
267 rtc::SSLIdentity::Generate("session2", rtc::KT_DEFAULT)) | |
268 .Pass()); | |
269 rtc::scoped_refptr<rtc::RTCCertificate> returned_certificate; | |
270 | |
271 FakeTransportChannel* channel1 = CreateChannel("audio", 1); | |
272 ASSERT_NE(nullptr, channel1); | |
273 | |
274 EXPECT_TRUE(transport_controller_->SetLocalCertificate(certificate1)); | |
275 EXPECT_TRUE(transport_controller_->GetLocalCertificate( | |
276 "audio", &returned_certificate)); | |
277 EXPECT_EQ(certificate1->identity()->certificate().ToPEMString(), | |
278 returned_certificate->identity()->certificate().ToPEMString()); | |
279 | |
280 // Should fail if called for a nonexistant transport. | |
281 EXPECT_FALSE(transport_controller_->GetLocalCertificate( | |
282 "video", &returned_certificate)); | |
283 | |
284 // Test that identity stored in controller is applied to new channels. | |
285 FakeTransportChannel* channel2 = CreateChannel("video", 1); | |
286 ASSERT_NE(nullptr, channel2); | |
287 EXPECT_TRUE(transport_controller_->GetLocalCertificate( | |
288 "video", &returned_certificate)); | |
289 EXPECT_EQ(certificate1->identity()->certificate().ToPEMString(), | |
290 returned_certificate->identity()->certificate().ToPEMString()); | |
291 | |
292 // Shouldn't be able to change the identity once set. | |
293 EXPECT_FALSE(transport_controller_->SetLocalCertificate(certificate2)); | |
294 } | |
295 | |
296 TEST_F(TransportControllerTest, TestGetRemoteSSLCertificate) { | |
297 rtc::FakeSSLCertificate fake_certificate("fake_data"); | |
298 rtc::scoped_ptr<rtc::SSLCertificate> returned_certificate; | |
299 | |
300 FakeTransportChannel* channel = CreateChannel("audio", 1); | |
301 ASSERT_NE(nullptr, channel); | |
302 | |
303 channel->SetRemoteSSLCertificate(&fake_certificate); | |
304 EXPECT_TRUE(transport_controller_->GetRemoteSSLCertificate( | |
305 "audio", returned_certificate.accept())); | |
306 EXPECT_EQ(fake_certificate.ToPEMString(), | |
307 returned_certificate->ToPEMString()); | |
308 | |
309 // Should fail if called for a nonexistant transport. | |
310 EXPECT_FALSE(transport_controller_->GetRemoteSSLCertificate( | |
311 "video", returned_certificate.accept())); | |
312 } | |
313 | |
314 TEST_F(TransportControllerTest, TestSetLocalTransportDescription) { | |
315 FakeTransportChannel* channel = CreateChannel("audio", 1); | |
316 ASSERT_NE(nullptr, channel); | |
317 TransportDescription local_desc( | |
318 std::vector<std::string>(), kIceUfrag1, kIcePwd1, cricket::ICEMODE_FULL, | |
319 cricket::CONNECTIONROLE_ACTPASS, nullptr, Candidates()); | |
320 std::string err; | |
321 EXPECT_TRUE(transport_controller_->SetLocalTransportDescription( | |
322 "audio", local_desc, cricket::CA_OFFER, &err)); | |
323 // Check that ICE ufrag and pwd were propagated to channel. | |
324 EXPECT_EQ(kIceUfrag1, channel->ice_ufrag()); | |
325 EXPECT_EQ(kIcePwd1, channel->ice_pwd()); | |
326 // We also expect that the channel started gathering as a result of the | |
327 // description being set. | |
328 EXPECT_EQ_WAIT(cricket::kIceGatheringGathering, gathering_state_, kTimeout); | |
329 EXPECT_EQ(1, gathering_state_signal_count_); | |
330 } | |
331 | |
332 TEST_F(TransportControllerTest, TestSetRemoteTransportDescription) { | |
333 FakeTransportChannel* channel = CreateChannel("audio", 1); | |
334 ASSERT_NE(nullptr, channel); | |
335 TransportDescription remote_desc( | |
336 std::vector<std::string>(), kIceUfrag1, kIcePwd1, cricket::ICEMODE_FULL, | |
337 cricket::CONNECTIONROLE_ACTPASS, nullptr, Candidates()); | |
338 std::string err; | |
339 EXPECT_TRUE(transport_controller_->SetRemoteTransportDescription( | |
340 "audio", remote_desc, cricket::CA_OFFER, &err)); | |
341 // Check that ICE ufrag and pwd were propagated to channel. | |
342 EXPECT_EQ(kIceUfrag1, channel->remote_ice_ufrag()); | |
343 EXPECT_EQ(kIcePwd1, channel->remote_ice_pwd()); | |
344 } | |
345 | |
346 TEST_F(TransportControllerTest, TestAddRemoteCandidates) { | |
347 FakeTransportChannel* channel = CreateChannel("audio", 1); | |
348 ASSERT_NE(nullptr, channel); | |
349 Candidates candidates; | |
350 candidates.push_back(CreateCandidate(1)); | |
351 std::string err; | |
352 EXPECT_TRUE( | |
353 transport_controller_->AddRemoteCandidates("audio", candidates, &err)); | |
354 EXPECT_EQ(1U, channel->remote_candidates().size()); | |
355 } | |
356 | |
357 TEST_F(TransportControllerTest, TestReadyForRemoteCandidates) { | |
358 FakeTransportChannel* channel = CreateChannel("audio", 1); | |
359 ASSERT_NE(nullptr, channel); | |
360 // We expect to be ready for remote candidates only after local and remote | |
361 // descriptions are set. | |
362 EXPECT_FALSE(transport_controller_->ReadyForRemoteCandidates("audio")); | |
363 | |
364 std::string err; | |
365 TransportDescription remote_desc( | |
366 std::vector<std::string>(), kIceUfrag1, kIcePwd1, cricket::ICEMODE_FULL, | |
367 cricket::CONNECTIONROLE_ACTPASS, nullptr, Candidates()); | |
368 EXPECT_TRUE(transport_controller_->SetRemoteTransportDescription( | |
369 "audio", remote_desc, cricket::CA_OFFER, &err)); | |
370 EXPECT_FALSE(transport_controller_->ReadyForRemoteCandidates("audio")); | |
371 | |
372 TransportDescription local_desc( | |
373 std::vector<std::string>(), kIceUfrag2, kIcePwd2, cricket::ICEMODE_FULL, | |
374 cricket::CONNECTIONROLE_ACTPASS, nullptr, Candidates()); | |
375 EXPECT_TRUE(transport_controller_->SetLocalTransportDescription( | |
376 "audio", local_desc, cricket::CA_ANSWER, &err)); | |
377 EXPECT_TRUE(transport_controller_->ReadyForRemoteCandidates("audio")); | |
378 } | |
379 | |
380 TEST_F(TransportControllerTest, TestGetStats) { | |
381 FakeTransportChannel* channel1 = CreateChannel("audio", 1); | |
382 ASSERT_NE(nullptr, channel1); | |
383 FakeTransportChannel* channel2 = CreateChannel("audio", 2); | |
384 ASSERT_NE(nullptr, channel2); | |
385 FakeTransportChannel* channel3 = CreateChannel("video", 1); | |
386 ASSERT_NE(nullptr, channel3); | |
387 | |
388 TransportStats stats; | |
389 EXPECT_TRUE(transport_controller_->GetStats("audio", &stats)); | |
390 EXPECT_EQ("audio", stats.transport_name); | |
391 EXPECT_EQ(2U, stats.channel_stats.size()); | |
392 } | |
393 | |
394 // Test that transport gets destroyed when it has no more channels. | |
395 TEST_F(TransportControllerTest, TestCreateAndDestroyChannel) { | |
396 FakeTransportChannel* channel1 = CreateChannel("audio", 1); | |
397 ASSERT_NE(nullptr, channel1); | |
398 FakeTransportChannel* channel2 = CreateChannel("audio", 1); | |
399 ASSERT_NE(nullptr, channel2); | |
400 ASSERT_EQ(channel1, channel2); | |
401 FakeTransportChannel* channel3 = CreateChannel("audio", 2); | |
402 ASSERT_NE(nullptr, channel3); | |
403 | |
404 // Using GetStats to check if transport is destroyed from an outside class's | |
405 // perspective. | |
406 TransportStats stats; | |
407 EXPECT_TRUE(transport_controller_->GetStats("audio", &stats)); | |
408 DestroyChannel("audio", 2); | |
409 DestroyChannel("audio", 1); | |
410 EXPECT_TRUE(transport_controller_->GetStats("audio", &stats)); | |
411 DestroyChannel("audio", 1); | |
412 EXPECT_FALSE(transport_controller_->GetStats("audio", &stats)); | |
413 } | |
414 | |
415 TEST_F(TransportControllerTest, TestSignalConnectionStateFailed) { | |
416 // Need controlling ICE role to get in failed state. | |
417 transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLING); | |
418 FakeTransportChannel* channel1 = CreateChannel("audio", 1); | |
419 ASSERT_NE(nullptr, channel1); | |
420 FakeTransportChannel* channel2 = CreateChannel("video", 1); | |
421 ASSERT_NE(nullptr, channel2); | |
422 | |
423 // Should signal "failed" if any channel failed; channel is considered failed | |
424 // if it previously had a connection but now has none, and gathering is | |
425 // complete. | |
426 channel1->SetCandidatesGatheringComplete(); | |
427 channel1->SetConnectionCount(1); | |
428 channel1->SetConnectionCount(0); | |
429 EXPECT_EQ_WAIT(cricket::kIceConnectionFailed, connection_state_, kTimeout); | |
430 EXPECT_EQ(1, connection_state_signal_count_); | |
431 } | |
432 | |
433 TEST_F(TransportControllerTest, TestSignalConnectionStateConnected) { | |
434 transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLING); | |
435 FakeTransportChannel* channel1 = CreateChannel("audio", 1); | |
436 ASSERT_NE(nullptr, channel1); | |
437 FakeTransportChannel* channel2 = CreateChannel("video", 1); | |
438 ASSERT_NE(nullptr, channel2); | |
439 FakeTransportChannel* channel3 = CreateChannel("video", 2); | |
440 ASSERT_NE(nullptr, channel3); | |
441 | |
442 // First, have one channel connect, and another fail, to ensure that | |
443 // the first channel connecting didn't trigger a "connected" state signal. | |
444 // We should only get a signal when all are connected. | |
445 channel1->SetConnectionCount(2); | |
446 channel1->SetWritable(true); | |
447 channel3->SetCandidatesGatheringComplete(); | |
448 channel3->SetConnectionCount(1); | |
449 channel3->SetConnectionCount(0); | |
450 EXPECT_EQ_WAIT(cricket::kIceConnectionFailed, connection_state_, kTimeout); | |
451 // Signal count of 1 means that the only signal emitted was "failed". | |
452 EXPECT_EQ(1, connection_state_signal_count_); | |
453 | |
454 // Destroy the failed channel to return to "connecting" state. | |
455 DestroyChannel("video", 2); | |
456 EXPECT_EQ_WAIT(cricket::kIceConnectionConnecting, connection_state_, | |
457 kTimeout); | |
458 EXPECT_EQ(2, connection_state_signal_count_); | |
459 | |
460 // Make the remaining channel reach a connected state. | |
461 channel2->SetConnectionCount(2); | |
462 channel2->SetWritable(true); | |
463 EXPECT_EQ_WAIT(cricket::kIceConnectionConnected, connection_state_, kTimeout); | |
464 EXPECT_EQ(3, connection_state_signal_count_); | |
465 } | |
466 | |
467 TEST_F(TransportControllerTest, TestSignalConnectionStateComplete) { | |
468 transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLING); | |
469 FakeTransportChannel* channel1 = CreateChannel("audio", 1); | |
470 ASSERT_NE(nullptr, channel1); | |
471 FakeTransportChannel* channel2 = CreateChannel("video", 1); | |
472 ASSERT_NE(nullptr, channel2); | |
473 FakeTransportChannel* channel3 = CreateChannel("video", 2); | |
474 ASSERT_NE(nullptr, channel3); | |
475 | |
476 // Similar to above test, but we're now reaching the completed state, which | |
477 // means only one connection per FakeTransportChannel. | |
478 channel1->SetCandidatesGatheringComplete(); | |
479 channel1->SetConnectionCount(1); | |
480 channel1->SetWritable(true); | |
481 channel3->SetCandidatesGatheringComplete(); | |
482 channel3->SetConnectionCount(1); | |
483 channel3->SetConnectionCount(0); | |
484 EXPECT_EQ_WAIT(cricket::kIceConnectionFailed, connection_state_, kTimeout); | |
485 // Signal count of 1 means that the only signal emitted was "failed". | |
486 EXPECT_EQ(1, connection_state_signal_count_); | |
487 | |
488 // Destroy the failed channel to return to "connecting" state. | |
489 DestroyChannel("video", 2); | |
490 EXPECT_EQ_WAIT(cricket::kIceConnectionConnecting, connection_state_, | |
491 kTimeout); | |
492 EXPECT_EQ(2, connection_state_signal_count_); | |
493 | |
494 // Make the remaining channel reach a connected state. | |
495 channel2->SetCandidatesGatheringComplete(); | |
496 channel2->SetConnectionCount(2); | |
497 channel2->SetWritable(true); | |
498 EXPECT_EQ_WAIT(cricket::kIceConnectionConnected, connection_state_, kTimeout); | |
499 EXPECT_EQ(3, connection_state_signal_count_); | |
500 | |
501 // Finally, transition to completed state. | |
502 channel2->SetConnectionCount(1); | |
503 EXPECT_EQ_WAIT(cricket::kIceConnectionCompleted, connection_state_, kTimeout); | |
504 EXPECT_EQ(4, connection_state_signal_count_); | |
505 } | |
506 | |
507 // Make sure that if we're "connected" and remove a transport, we stay in the | |
508 // "connected" state. | |
pthatcher1
2015/09/09 06:47:52
Do you mean "completed" state? That's what it's a
Taylor Brandstetter
2015/09/10 01:17:48
If you look closely, we connect two transports, de
| |
509 TEST_F(TransportControllerTest, TestDestroyTransportAndStayConnected) { | |
510 FakeTransportChannel* channel1 = CreateChannel("audio", 1); | |
511 ASSERT_NE(nullptr, channel1); | |
512 FakeTransportChannel* channel2 = CreateChannel("video", 1); | |
513 ASSERT_NE(nullptr, channel2); | |
514 | |
515 channel1->SetCandidatesGatheringComplete(); | |
516 channel1->SetConnectionCount(2); | |
517 channel1->SetWritable(true); | |
518 channel2->SetCandidatesGatheringComplete(); | |
519 channel2->SetConnectionCount(2); | |
520 channel2->SetWritable(true); | |
521 EXPECT_EQ_WAIT(cricket::kIceConnectionConnected, connection_state_, kTimeout); | |
522 EXPECT_EQ(1, connection_state_signal_count_); | |
523 | |
524 // Destroy one channel, then "complete" the other one, so we reach | |
525 // a known state. | |
526 DestroyChannel("video", 1); | |
527 channel1->SetConnectionCount(1); | |
528 EXPECT_EQ_WAIT(cricket::kIceConnectionCompleted, connection_state_, kTimeout); | |
529 // Signal count of 2 means the deletion didn't cause any unexpected signals | |
530 EXPECT_EQ(2, connection_state_signal_count_); | |
531 } | |
532 | |
533 // If we destroy the last/only transport, we should simply transition to | |
534 // "connecting". | |
pthatcher1
2015/09/09 06:47:52
Why "connecting"? Shouldn't it go to "disconnecte
Taylor Brandstetter
2015/09/10 01:17:48
As mentioned in the other comment, there's no cric
| |
535 TEST_F(TransportControllerTest, TestDestroyLastTransportWhileConnected) { | |
536 FakeTransportChannel* channel = CreateChannel("audio", 1); | |
537 ASSERT_NE(nullptr, channel); | |
538 | |
539 channel->SetCandidatesGatheringComplete(); | |
540 channel->SetConnectionCount(2); | |
541 channel->SetWritable(true); | |
542 EXPECT_EQ_WAIT(cricket::kIceConnectionConnected, connection_state_, kTimeout); | |
543 EXPECT_EQ(1, connection_state_signal_count_); | |
544 | |
545 DestroyChannel("audio", 1); | |
546 EXPECT_EQ_WAIT(cricket::kIceConnectionConnecting, connection_state_, | |
547 kTimeout); | |
548 // Signal count of 2 means the deletion didn't cause any unexpected signals | |
549 EXPECT_EQ(2, connection_state_signal_count_); | |
550 } | |
551 | |
552 TEST_F(TransportControllerTest, TestSignalReceiving) { | |
553 FakeTransportChannel* channel1 = CreateChannel("audio", 1); | |
554 ASSERT_NE(nullptr, channel1); | |
555 FakeTransportChannel* channel2 = CreateChannel("video", 1); | |
556 ASSERT_NE(nullptr, channel2); | |
557 | |
558 // Should signal receiving as soon as any channel is receiving. | |
559 channel1->SetReceiving(true); | |
560 EXPECT_TRUE_WAIT(receiving_, kTimeout); | |
561 EXPECT_EQ(1, receiving_signal_count_); | |
562 | |
563 channel2->SetReceiving(true); | |
564 channel1->SetReceiving(false); | |
565 channel2->SetReceiving(false); | |
566 EXPECT_TRUE_WAIT(!receiving_, kTimeout); | |
567 EXPECT_EQ(2, receiving_signal_count_); | |
568 } | |
569 | |
570 TEST_F(TransportControllerTest, TestSignalGatheringStateGathering) { | |
571 FakeTransportChannel* channel1 = CreateChannel("audio", 1); | |
572 ASSERT_NE(nullptr, channel1); | |
573 FakeTransportChannel* channel2 = CreateChannel("video", 1); | |
574 ASSERT_NE(nullptr, channel2); | |
575 // Connect starts candidate gathering. | |
576 channel1->Connect(); | |
577 // Should be in the gathering state as soon as any transport starts gathering. | |
578 EXPECT_EQ_WAIT(cricket::kIceGatheringGathering, gathering_state_, kTimeout); | |
579 EXPECT_EQ(1, gathering_state_signal_count_); | |
580 } | |
581 | |
582 TEST_F(TransportControllerTest, TestSignalGatheringStateComplete) { | |
583 FakeTransportChannel* channel1 = CreateChannel("audio", 1); | |
584 ASSERT_NE(nullptr, channel1); | |
585 FakeTransportChannel* channel2 = CreateChannel("video", 1); | |
586 ASSERT_NE(nullptr, channel2); | |
587 FakeTransportChannel* channel3 = CreateChannel("data", 1); | |
588 ASSERT_NE(nullptr, channel3); | |
589 | |
590 channel3->Connect(); | |
591 EXPECT_EQ_WAIT(cricket::kIceGatheringGathering, gathering_state_, kTimeout); | |
592 EXPECT_EQ(1, gathering_state_signal_count_); | |
593 | |
594 // Have one channel finish gathering, then destroy it, to make sure gathering | |
595 // completion wasn't signalled if only one transport finished gathering. | |
596 channel3->SetCandidatesGatheringComplete(); | |
597 DestroyChannel("data", 1); | |
598 EXPECT_EQ_WAIT(cricket::kIceGatheringNew, gathering_state_, kTimeout); | |
599 EXPECT_EQ(2, gathering_state_signal_count_); | |
600 | |
601 // Make remaining channels start and then finish gathering. | |
602 channel1->Connect(); | |
603 channel2->Connect(); | |
604 EXPECT_EQ_WAIT(cricket::kIceGatheringGathering, gathering_state_, kTimeout); | |
605 EXPECT_EQ(3, gathering_state_signal_count_); | |
606 | |
607 channel1->SetCandidatesGatheringComplete(); | |
608 channel2->SetCandidatesGatheringComplete(); | |
609 EXPECT_EQ_WAIT(cricket::kIceGatheringComplete, gathering_state_, kTimeout); | |
610 EXPECT_EQ(4, gathering_state_signal_count_); | |
611 } | |
612 | |
613 // Test that when the last transport that hasn't finished connecting and/or | |
614 // gathering is destroyed, the aggregate state jumps to "completed". This can | |
615 // happen if, for example, we have an audio and video transport, the audio | |
616 // transport completes, then we start bundling video on the audio transport. | |
617 TEST_F(TransportControllerTest, | |
618 TestSignalingWhenLastIncompleteTransportDestroyed) { | |
619 transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLING); | |
620 FakeTransportChannel* channel1 = CreateChannel("audio", 1); | |
621 ASSERT_NE(nullptr, channel1); | |
622 FakeTransportChannel* channel2 = CreateChannel("video", 1); | |
623 ASSERT_NE(nullptr, channel2); | |
624 | |
625 channel1->SetCandidatesGatheringComplete(); | |
626 EXPECT_EQ_WAIT(cricket::kIceGatheringGathering, gathering_state_, kTimeout); | |
627 EXPECT_EQ(1, gathering_state_signal_count_); | |
628 | |
629 channel1->SetConnectionCount(1); | |
630 channel1->SetWritable(true); | |
631 DestroyChannel("video", 1); | |
632 EXPECT_EQ_WAIT(cricket::kIceConnectionCompleted, connection_state_, kTimeout); | |
633 EXPECT_EQ(1, connection_state_signal_count_); | |
634 EXPECT_EQ_WAIT(cricket::kIceGatheringComplete, gathering_state_, kTimeout); | |
635 EXPECT_EQ(2, gathering_state_signal_count_); | |
636 } | |
637 | |
638 TEST_F(TransportControllerTest, TestSignalCandidatesGathered) { | |
639 FakeTransportChannel* channel = CreateChannel("audio", 1); | |
640 ASSERT_NE(nullptr, channel); | |
641 | |
642 // Transport won't signal candidates until it has a local description. | |
643 TransportDescription local_desc( | |
644 std::vector<std::string>(), kIceUfrag1, kIcePwd1, cricket::ICEMODE_FULL, | |
645 cricket::CONNECTIONROLE_ACTPASS, nullptr, Candidates()); | |
646 std::string err; | |
647 EXPECT_TRUE(transport_controller_->SetLocalTransportDescription( | |
648 "audio", local_desc, cricket::CA_OFFER, &err)); | |
649 | |
650 channel->SignalCandidateGathered(channel, CreateCandidate(1)); | |
651 EXPECT_EQ_WAIT(1, candidates_signal_count_, kTimeout); | |
652 EXPECT_EQ(1U, candidates_["audio"].size()); | |
653 } | |
654 | |
655 TEST_F(TransportControllerTest, TestSignalingOccursOnSignalingThread) { | |
656 CreateTransportControllerWithWorkerThread(); | |
657 CreateChannelsAndCompleteConnectionOnWorkerThread(); | |
658 | |
659 // connecting --> connected --> completed | |
660 EXPECT_EQ_WAIT(cricket::kIceConnectionCompleted, connection_state_, kTimeout); | |
661 EXPECT_EQ(2, connection_state_signal_count_); | |
662 | |
663 EXPECT_TRUE_WAIT(receiving_, kTimeout); | |
664 EXPECT_EQ(1, receiving_signal_count_); | |
665 | |
666 // new --> gathering --> complete | |
667 EXPECT_EQ_WAIT(cricket::kIceGatheringComplete, gathering_state_, kTimeout); | |
668 EXPECT_EQ(2, gathering_state_signal_count_); | |
669 | |
670 EXPECT_EQ_WAIT(1U, candidates_["audio"].size(), kTimeout); | |
671 EXPECT_EQ_WAIT(1U, candidates_["video"].size(), kTimeout); | |
672 EXPECT_EQ(2, candidates_signal_count_); | |
673 | |
674 EXPECT_TRUE(!signaled_on_non_signaling_thread_); | |
675 } | |
OLD | NEW |