Index: webrtc/p2p/base/port_unittest.cc |
diff --git a/webrtc/p2p/base/port_unittest.cc b/webrtc/p2p/base/port_unittest.cc |
index e84af9f2be848638e9b167344d639fdbdce92c27..c4de8d6b1dd090d6db9ffa0e1365c7d682608e92 100644 |
--- a/webrtc/p2p/base/port_unittest.cc |
+++ b/webrtc/p2p/base/port_unittest.cc |
@@ -384,7 +384,7 @@ class PortTest : public testing::Test, public sigslot::has_slots<> { |
username_(rtc::CreateRandomString(ICE_UFRAG_LENGTH)), |
password_(rtc::CreateRandomString(ICE_PWD_LENGTH)), |
role_conflict_(false), |
- destroyed_(false) { |
+ ports_destroyed_(0) { |
network_.AddIP(rtc::IPAddress(INADDR_ANY)); |
} |
@@ -755,10 +755,8 @@ class PortTest : public testing::Test, public sigslot::has_slots<> { |
port->SignalDestroyed.connect(this, &PortTest::OnDestroyed); |
} |
- void OnDestroyed(PortInterface* port) { |
- destroyed_ = true; |
- } |
- bool destroyed() const { return destroyed_; } |
+ void OnDestroyed(PortInterface* port) { ++ports_destroyed_; } |
+ int ports_destroyed() const { return ports_destroyed_; } |
rtc::BasicPacketSocketFactory* nat_socket_factory1() { |
return &nat_socket_factory1_; |
@@ -785,7 +783,7 @@ class PortTest : public testing::Test, public sigslot::has_slots<> { |
std::string username_; |
std::string password_; |
bool role_conflict_; |
- bool destroyed_; |
+ int ports_destroyed_; |
}; |
void PortTest::TestConnectivity(const char* name1, Port* port1, |
@@ -2567,15 +2565,21 @@ TEST_F(PortTest, TestIceLiteConnectivity) { |
ch1.Stop(); |
} |
-// This test case verifies that the CONTROLLING port does not time out. |
-TEST_F(PortTest, TestControllingNoTimeout) { |
+// This test case verifies that both the controlling port and the controlled |
+// port will time out after connectivity is lost, if they are not marked as |
+// "keep alive until pruned." |
+TEST_F(PortTest, TestPortTimeoutIfNotKeptAlive) { |
+ rtc::ScopedFakeClock clock; |
+ int timeout_delay = 100; |
UDPPort* port1 = CreateUdpPort(kLocalAddr1); |
ConnectToSignalDestroyed(port1); |
- port1->set_timeout_delay(10); // milliseconds |
+ port1->set_timeout_delay(timeout_delay); // milliseconds |
port1->SetIceRole(cricket::ICEROLE_CONTROLLING); |
port1->SetIceTiebreaker(kTiebreaker1); |
UDPPort* port2 = CreateUdpPort(kLocalAddr2); |
+ ConnectToSignalDestroyed(port2); |
+ port2->set_timeout_delay(timeout_delay); // milliseconds |
port2->SetIceRole(cricket::ICEROLE_CONTROLLED); |
port2->SetIceTiebreaker(kTiebreaker2); |
@@ -2585,90 +2589,91 @@ TEST_F(PortTest, TestControllingNoTimeout) { |
// Simulate a connection that succeeds, and then is destroyed. |
StartConnectAndStopChannels(&ch1, &ch2); |
- |
- // After the connection is destroyed, the port should not be destroyed. |
- rtc::Thread::Current()->ProcessMessages(kTimeout); |
- EXPECT_FALSE(destroyed()); |
+ // After the connection is destroyed, the port will be destroyed because |
+ // none of them is marked as "keep alive until pruned. |
+ EXPECT_EQ_SIMULATED_WAIT(2, ports_destroyed(), 110, clock); |
} |
-// This test case verifies that the CONTROLLED port does time out, but only |
-// after connectivity is lost and no connection was created during the timeout |
-// period. |
-TEST_F(PortTest, TestControlledTimeout) { |
+// Test that if after all connection are destroyed, new connections are created |
+// and destroyed again, ports won't be destroyed until a timeout period passes |
+// after the last set of connections are all destroyed. |
+TEST_F(PortTest, TestPortTimeoutAfterNewConnectionCreatedAndDestroyed) { |
rtc::ScopedFakeClock clock; |
+ int timeout_delay = 100; |
UDPPort* port1 = CreateUdpPort(kLocalAddr1); |
+ ConnectToSignalDestroyed(port1); |
+ port1->set_timeout_delay(timeout_delay); // milliseconds |
port1->SetIceRole(cricket::ICEROLE_CONTROLLING); |
port1->SetIceTiebreaker(kTiebreaker1); |
UDPPort* port2 = CreateUdpPort(kLocalAddr2); |
ConnectToSignalDestroyed(port2); |
- port2->set_timeout_delay(100); // milliseconds |
+ port2->set_timeout_delay(timeout_delay); // milliseconds |
+ |
port2->SetIceRole(cricket::ICEROLE_CONTROLLED); |
port2->SetIceTiebreaker(kTiebreaker2); |
- // The connection must not be destroyed before a connection is attempted. |
- EXPECT_FALSE(destroyed()); |
- |
- port1->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT); |
- port2->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT); |
- |
// Set up channels and ensure both ports will be deleted. |
TestChannel ch1(port1); |
TestChannel ch2(port2); |
// Simulate a connection that succeeds, and then is destroyed. |
StartConnectAndStopChannels(&ch1, &ch2); |
+ SIMULATED_WAIT(ports_destroyed() > 0, 80, clock); |
+ EXPECT_EQ(0, ports_destroyed()); |
- SIMULATED_WAIT(false, 80, clock); |
+ // Start the second set of connection and destroy them. |
+ ch1.CreateConnection(GetCandidate(ch2.port())); |
ch2.CreateConnection(GetCandidate(ch1.port())); |
- |
- // ch2 creates a connection so it will not be destroyed. |
- SIMULATED_WAIT(destroyed(), 80, clock); |
- EXPECT_FALSE(destroyed()); |
- |
- // Even if ch2 stops now, it won't be destroyed until 100ms after the |
- // connection is destroyed. |
+ ch1.Stop(); |
ch2.Stop(); |
- SIMULATED_WAIT(destroyed(), 80, clock); |
- EXPECT_FALSE(destroyed()); |
- // The controlled port should be destroyed after timeout. |
- EXPECT_TRUE_SIMULATED_WAIT(destroyed(), 30, clock); |
+ SIMULATED_WAIT(ports_destroyed() > 0, 80, clock); |
+ EXPECT_EQ(0, ports_destroyed()); |
+ |
+ // The ports on both sides should be destroyed after timeout. |
+ EXPECT_TRUE_SIMULATED_WAIT(ports_destroyed() == 2, 30, clock); |
} |
-// This test case verifies that if the role of a port changes from controlled |
-// to controlling after all connections fail, the port will not be destroyed. |
-TEST_F(PortTest, TestControlledToControllingNotDestroyed) { |
+// This test case verifies that neither the controlling port nor the controlled |
+// port will time out after connectivity is lost if they are marked as "keep |
+// alive until pruned". They will time out after they are pruned. |
+TEST_F(PortTest, TestPortNotTimeoutUntilPruned) { |
+ rtc::ScopedFakeClock clock; |
+ int timeout_delay = 100; |
UDPPort* port1 = CreateUdpPort(kLocalAddr1); |
+ ConnectToSignalDestroyed(port1); |
+ port1->set_timeout_delay(timeout_delay); // milliseconds |
port1->SetIceRole(cricket::ICEROLE_CONTROLLING); |
port1->SetIceTiebreaker(kTiebreaker1); |
UDPPort* port2 = CreateUdpPort(kLocalAddr2); |
ConnectToSignalDestroyed(port2); |
- port2->set_timeout_delay(10); // milliseconds |
+ port2->set_timeout_delay(timeout_delay); // milliseconds |
port2->SetIceRole(cricket::ICEROLE_CONTROLLED); |
port2->SetIceTiebreaker(kTiebreaker2); |
- |
// The connection must not be destroyed before a connection is attempted. |
- EXPECT_FALSE(destroyed()); |
+ EXPECT_EQ(0, ports_destroyed()); |
port1->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT); |
port2->set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT); |
- // Set up channels and ensure both ports will be deleted. |
+ // Set up channels and keep the port alive. |
TestChannel ch1(port1); |
TestChannel ch2(port2); |
- |
- // Simulate a connection that succeeds, and then is destroyed. |
+ // Simulate a connection that succeeds, and then is destroyed. But ports |
+ // are kept alive. Ports won't be destroyed. |
StartConnectAndStopChannels(&ch1, &ch2); |
- // Switch the role after all connections are destroyed. |
- EXPECT_TRUE_WAIT(ch2.conn() == nullptr, kTimeout); |
- port1->SetIceRole(cricket::ICEROLE_CONTROLLED); |
- port2->SetIceRole(cricket::ICEROLE_CONTROLLING); |
- |
- // After the connection is destroyed, the port should not be destroyed. |
- rtc::Thread::Current()->ProcessMessages(kTimeout); |
- EXPECT_FALSE(destroyed()); |
+ port1->KeepAliveUntilPruned(); |
+ port2->KeepAliveUntilPruned(); |
+ SIMULATED_WAIT(ports_destroyed() > 0, 150, clock); |
+ EXPECT_EQ(0, ports_destroyed()); |
+ |
+ // If they are pruned now, they will be destroyed right away. |
+ port1->Prune(); |
+ port2->Prune(); |
+ // The ports on both sides should be destroyed after timeout. |
+ EXPECT_TRUE_SIMULATED_WAIT(ports_destroyed() == 2, 1, clock); |
} |
TEST_F(PortTest, TestSupportsProtocol) { |