From 716d07a2414389638eba6ed03b704bf752a269ef Mon Sep 17 00:00:00 2001 From: Taylor Brandstetter Date: Mon, 27 Jun 2016 14:07:41 -0700 Subject: [PATCH] Using fake clock for TURN port tests and un-disabling some tests. The fake clock has a few advantages: 1. It lets use verify that operations take the expected number of round trips. 2. It makes the tests faster by letting us remove the equivalent of "Sleep(500)" all over the tests. 3. It makes the tests less flaky, because sometimes sleeping for 500ms or waiting for 1s is not enough. R=honghaiz@webrtc.org, pthatcher@webrtc.org Review URL: https://codereview.webrtc.org/2097793003 . Cr-Commit-Position: refs/heads/master@{#13304} --- webrtc/base/gunit.h | 75 +++-- webrtc/base/virtualsocketserver.cc | 5 +- webrtc/p2p/base/turnport_unittest.cc | 435 +++++++++++++++------------ webrtc/p2p/base/turnserver.cc | 5 +- 4 files changed, 299 insertions(+), 221 deletions(-) diff --git a/webrtc/base/gunit.h b/webrtc/base/gunit.h index ad52a43c82..b087badd94 100644 --- a/webrtc/base/gunit.h +++ b/webrtc/base/gunit.h @@ -21,25 +21,25 @@ #endif // Wait until "ex" is true, or "timeout" expires. -#define WAIT(ex, timeout) \ - for (int64_t start = rtc::SystemTimeMillis(); \ - !(ex) && rtc::SystemTimeMillis() < start + timeout;) { \ - rtc::Thread::Current()->ProcessMessages(0); \ - rtc::Thread::Current()->SleepMs(1); \ +#define WAIT(ex, timeout) \ + for (int64_t start = rtc::SystemTimeMillis(); \ + !(ex) && rtc::SystemTimeMillis() < start + (timeout);) { \ + rtc::Thread::Current()->ProcessMessages(0); \ + rtc::Thread::Current()->SleepMs(1); \ } // This returns the result of the test in res, so that we don't re-evaluate // the expression in the XXXX_WAIT macros below, since that causes problems // when the expression is only true the first time you check it. -#define WAIT_(ex, timeout, res) \ - do { \ - int64_t start = rtc::SystemTimeMillis(); \ - res = (ex); \ - while (!res && rtc::SystemTimeMillis() < start + timeout) { \ - rtc::Thread::Current()->ProcessMessages(0); \ - rtc::Thread::Current()->SleepMs(1); \ - res = (ex); \ - } \ +#define WAIT_(ex, timeout, res) \ + do { \ + int64_t start = rtc::SystemTimeMillis(); \ + res = (ex); \ + while (!res && rtc::SystemTimeMillis() < start + (timeout)) { \ + rtc::Thread::Current()->ProcessMessages(0); \ + rtc::Thread::Current()->SleepMs(1); \ + res = (ex); \ + } \ } while (0) // The typical EXPECT_XXXX and ASSERT_XXXXs, but done until true or a timeout. @@ -74,26 +74,27 @@ // Version with a "soft" timeout and a margin. This logs if the timeout is // exceeded, but it only fails if the expression still isn't true after the // margin time passes. -#define EXPECT_TRUE_WAIT_MARGIN(ex, timeout, margin) \ - do { \ - bool res; \ - WAIT_(ex, timeout, res); \ - if (res) { \ - break; \ - } \ - LOG(LS_WARNING) << "Expression " << #ex << " still not true after " << \ - timeout << "ms; waiting an additional " << margin << "ms"; \ - WAIT_(ex, margin, res); \ - if (!res) { \ - EXPECT_TRUE(ex); \ - } \ +#define EXPECT_TRUE_WAIT_MARGIN(ex, timeout, margin) \ + do { \ + bool res; \ + WAIT_(ex, timeout, res); \ + if (res) { \ + break; \ + } \ + LOG(LS_WARNING) << "Expression " << #ex << " still not true after " \ + << (timeout) << "ms; waiting an additional " << margin \ + << "ms"; \ + WAIT_(ex, margin, res); \ + if (!res) { \ + EXPECT_TRUE(ex); \ + } \ } while (0) // Wait until "ex" is true, or "timeout" expires, using fake clock where // messages are processed every millisecond. #define SIMULATED_WAIT(ex, timeout, clock) \ for (int64_t start = rtc::TimeMillis(); \ - !(ex) && rtc::TimeMillis() < start + timeout;) { \ + !(ex) && rtc::TimeMillis() < start + (timeout);) { \ clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1)); \ } @@ -104,7 +105,7 @@ do { \ int64_t start = rtc::TimeMillis(); \ res = (ex); \ - while (!res && rtc::TimeMillis() < start + timeout) { \ + while (!res && rtc::TimeMillis() < start + (timeout)) { \ clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1)); \ res = (ex); \ } \ @@ -129,4 +130,20 @@ } \ } while (0) +#define ASSERT_TRUE_SIMULATED_WAIT(ex, timeout, clock) \ + do { \ + bool res; \ + SIMULATED_WAIT_(ex, timeout, res, clock); \ + if (!res) \ + ASSERT_TRUE(ex); \ + } while (0) + +#define ASSERT_EQ_SIMULATED_WAIT(v1, v2, timeout, clock) \ + do { \ + bool res; \ + SIMULATED_WAIT_(v1 == v2, timeout, res, clock); \ + if (!res) \ + ASSERT_EQ(v1, v2); \ + } while (0) + #endif // WEBRTC_BASE_GUNIT_H_ diff --git a/webrtc/base/virtualsocketserver.cc b/webrtc/base/virtualsocketserver.cc index d871d4c137..ef3c6e5329 100644 --- a/webrtc/base/virtualsocketserver.cc +++ b/webrtc/base/virtualsocketserver.cc @@ -771,8 +771,11 @@ int VirtualSocketServer::Connect(VirtualSocket* socket, bool VirtualSocketServer::Disconnect(VirtualSocket* socket) { if (socket) { + // If we simulate packets being delayed, we should simulate the + // equivalent of a FIN being delayed as well. + uint32_t delay = GetRandomTransitDelay(); // Remove the mapping. - msg_queue_->Post(RTC_FROM_HERE, socket, MSG_ID_DISCONNECT); + msg_queue_->PostDelayed(RTC_FROM_HERE, delay, socket, MSG_ID_DISCONNECT); return true; } return false; diff --git a/webrtc/p2p/base/turnport_unittest.cc b/webrtc/p2p/base/turnport_unittest.cc index 077ca4d7f1..ef678b5d73 100644 --- a/webrtc/p2p/base/turnport_unittest.cc +++ b/webrtc/p2p/base/turnport_unittest.cc @@ -23,6 +23,7 @@ #include "webrtc/base/asynctcpsocket.h" #include "webrtc/base/buffer.h" #include "webrtc/base/dscp.h" +#include "webrtc/base/fakeclock.h" #include "webrtc/base/firewallsocketserver.h" #include "webrtc/base/gunit.h" #include "webrtc/base/helpers.h" @@ -34,11 +35,6 @@ #include "webrtc/base/virtualsocketserver.h" using rtc::SocketAddress; -using cricket::Connection; -using cricket::Port; -using cricket::PortInterface; -using cricket::TurnPort; -using cricket::UDPPort; static const SocketAddress kLocalAddr1("11.11.11.11", 0); static const SocketAddress kLocalAddr2("22.22.22.22", 0); @@ -69,7 +65,15 @@ static const char kIcePwd2[] = "TESTICEPWD00000000000002"; static const char kTurnUsername[] = "test"; static const char kTurnPassword[] = "test"; static const char kTestOrigin[] = "http://example.com"; -static const unsigned int kTimeout = 1000; +// This test configures the virtual socket server to simulate delay so that we +// can verify operations take no more than the expected number of round trips. +static constexpr unsigned int kSimulatedRtt = 50; +// Connection destruction may happen asynchronously, but it should only +// take one simulated clock tick. +static constexpr unsigned int kConnectionDestructionDelay = 1; +// This used to be 1 second, but that's not always enough for getaddrinfo(). +// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5191 +static constexpr unsigned int kResolverTimeout = 10000; static const cricket::ProtocolAddress kTurnUdpProtoAddr( kTurnUdpIntAddr, cricket::PROTO_UDP); @@ -95,10 +99,17 @@ static int GetFDCount() { } #endif +namespace cricket { + class TurnPortTestVirtualSocketServer : public rtc::VirtualSocketServer { public: explicit TurnPortTestVirtualSocketServer(SocketServer* ss) - : VirtualSocketServer(ss) {} + : VirtualSocketServer(ss) { + // This configures the virtual socket server to always add a simulated + // delay of exactly half of kSimulatedRtt. + set_delay_mean(kSimulatedRtt / 2); + UpdateDelayDistribution(); + } using rtc::VirtualSocketServer::LookupBinding; }; @@ -121,6 +132,8 @@ class TestConnectionWrapper : public sigslot::has_slots<> { Connection* connection_; }; +// Note: This test uses a fake clock with a simulated network round trip +// (between local port and TURN server) of kSimulatedRtt. class TurnPortTest : public testing::Test, public sigslot::has_slots<>, public rtc::MessageHandler { @@ -139,6 +152,10 @@ class TurnPortTest : public testing::Test, turn_create_permission_success_(false), udp_ready_(false), test_finish_(false) { + // Some code uses "last received time == 0" to represent "nothing received + // so far", so we need to start the fake clock at a nonzero time... + // TODO(deadbeef): Fix this. + fake_clock_.AdvanceTime(rtc::TimeDelta::FromSeconds(1)); network_.AddIP(rtc::IPAddress(INADDR_ANY)); } @@ -169,9 +186,11 @@ class TurnPortTest : public testing::Test, void OnTurnPortError(Port* port) { turn_error_ = true; } - void OnTurnUnknownAddress(PortInterface* port, const SocketAddress& addr, - cricket::ProtocolType proto, - cricket::IceMessage* msg, const std::string& rf, + void OnTurnUnknownAddress(PortInterface* port, + const SocketAddress& addr, + ProtocolType proto, + IceMessage* msg, + const std::string& rf, bool /*port_muxed*/) { turn_unknown_address_ = true; } @@ -212,21 +231,21 @@ class TurnPortTest : public testing::Test, void CreateTurnPort(const std::string& username, const std::string& password, - const cricket::ProtocolAddress& server_address) { + const ProtocolAddress& server_address) { CreateTurnPort(kLocalAddr1, username, password, server_address); } void CreateTurnPort(const rtc::SocketAddress& local_address, const std::string& username, const std::string& password, - const cricket::ProtocolAddress& server_address) { - cricket::RelayCredentials credentials(username, password); + const ProtocolAddress& server_address) { + RelayCredentials credentials(username, password); turn_port_.reset(TurnPort::Create(main_, &socket_factory_, &network_, local_address.ipaddr(), 0, 0, kIceUfrag1, kIcePwd1, server_address, credentials, 0, std::string())); // This TURN port will be the controlling. - turn_port_->SetIceRole(cricket::ICEROLE_CONTROLLING); + turn_port_->SetIceRole(ICEROLE_CONTROLLING); ConnectSignals(); } @@ -235,23 +254,23 @@ class TurnPortTest : public testing::Test, void CreateTurnPortWithOrigin(const rtc::SocketAddress& local_address, const std::string& username, const std::string& password, - const cricket::ProtocolAddress& server_address, + const ProtocolAddress& server_address, const std::string& origin) { - cricket::RelayCredentials credentials(username, password); + RelayCredentials credentials(username, password); turn_port_.reset(TurnPort::Create(main_, &socket_factory_, &network_, local_address.ipaddr(), 0, 0, kIceUfrag1, kIcePwd1, server_address, credentials, 0, origin)); // This TURN port will be the controlling. - turn_port_->SetIceRole(cricket::ICEROLE_CONTROLLING); + turn_port_->SetIceRole(ICEROLE_CONTROLLING); ConnectSignals(); } void CreateSharedTurnPort(const std::string& username, const std::string& password, - const cricket::ProtocolAddress& server_address) { - ASSERT(server_address.proto == cricket::PROTO_UDP); + const ProtocolAddress& server_address) { + ASSERT(server_address.proto == PROTO_UDP); if (!socket_) { socket_.reset(socket_factory_.CreateUdpSocket( @@ -261,12 +280,12 @@ class TurnPortTest : public testing::Test, this, &TurnPortTest::OnSocketReadPacket); } - cricket::RelayCredentials credentials(username, password); - turn_port_.reset(cricket::TurnPort::Create( - main_, &socket_factory_, &network_, socket_.get(), - kIceUfrag1, kIcePwd1, server_address, credentials, 0, std::string())); + RelayCredentials credentials(username, password); + turn_port_.reset(TurnPort::Create( + main_, &socket_factory_, &network_, socket_.get(), kIceUfrag1, kIcePwd1, + server_address, credentials, 0, std::string())); // This TURN port will be the controlling. - turn_port_->SetIceRole(cricket::ICEROLE_CONTROLLING); + turn_port_->SetIceRole(ICEROLE_CONTROLLING); ConnectSignals(); } @@ -290,20 +309,25 @@ class TurnPortTest : public testing::Test, address.ipaddr(), 0, 0, kIceUfrag2, kIcePwd2, std::string(), false)); // UDP port will be controlled. - udp_port_->SetIceRole(cricket::ICEROLE_CONTROLLED); + udp_port_->SetIceRole(ICEROLE_CONTROLLED); udp_port_->SignalPortComplete.connect( this, &TurnPortTest::OnUdpPortComplete); } - void PrepareTurnAndUdpPorts() { + void PrepareTurnAndUdpPorts(ProtocolType protocol_type) { // turn_port_ should have been created. ASSERT_TRUE(turn_port_ != nullptr); turn_port_->PrepareAddress(); - ASSERT_TRUE_WAIT(turn_ready_, kTimeout); + // Two round trips are required to allocate a TURN candidate. + // Plus, an extra round trip is needed for TCP. + ASSERT_TRUE_SIMULATED_WAIT( + turn_ready_, + protocol_type == PROTO_TCP ? kSimulatedRtt * 3 : kSimulatedRtt * 2, + fake_clock_); CreateUdpPort(); udp_port_->PrepareAddress(); - ASSERT_TRUE_WAIT(udp_ready_, kTimeout); + ASSERT_TRUE_SIMULATED_WAIT(udp_ready_, kSimulatedRtt, fake_clock_); } bool CheckConnectionFailedAndPruned(Connection* conn) { @@ -325,23 +349,27 @@ class TurnPortTest : public testing::Test, return true; } - void TestTurnAlternateServer(cricket::ProtocolType protocol_type) { + void TestTurnAlternateServer(ProtocolType protocol_type) { std::vector redirect_addresses; redirect_addresses.push_back(kTurnAlternateIntAddr); - cricket::TestTurnRedirector redirector(redirect_addresses); + TestTurnRedirector redirector(redirect_addresses); turn_server_.AddInternalSocket(kTurnIntAddr, protocol_type); turn_server_.AddInternalSocket(kTurnAlternateIntAddr, protocol_type); turn_server_.set_redirect_hook(&redirector); CreateTurnPort(kTurnUsername, kTurnPassword, - cricket::ProtocolAddress(kTurnIntAddr, protocol_type)); + ProtocolAddress(kTurnIntAddr, protocol_type)); // Retrieve the address before we run the state machine. const SocketAddress old_addr = turn_port_->server_address().address; turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_ready_, kTimeout * 100); + // Extra round trip due to "use alternate server" error response. + EXPECT_TRUE_SIMULATED_WAIT( + turn_ready_, + (protocol_type == PROTO_TCP ? kSimulatedRtt * 4 : kSimulatedRtt * 3), + fake_clock_); // Retrieve the address again, the turn port's address should be // changed. const SocketAddress new_addr = turn_port_->server_address().address; @@ -352,34 +380,38 @@ class TurnPortTest : public testing::Test, EXPECT_NE(0, turn_port_->Candidates()[0].address().port()); } - void TestTurnAlternateServerV4toV6(cricket::ProtocolType protocol_type) { + void TestTurnAlternateServerV4toV6(ProtocolType protocol_type) { std::vector redirect_addresses; redirect_addresses.push_back(kTurnIPv6IntAddr); - cricket::TestTurnRedirector redirector(redirect_addresses); + TestTurnRedirector redirector(redirect_addresses); turn_server_.AddInternalSocket(kTurnIntAddr, protocol_type); turn_server_.set_redirect_hook(&redirector); CreateTurnPort(kTurnUsername, kTurnPassword, - cricket::ProtocolAddress(kTurnIntAddr, protocol_type)); + ProtocolAddress(kTurnIntAddr, protocol_type)); turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_error_, kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(turn_error_, kSimulatedRtt * 2, fake_clock_); } - void TestTurnAlternateServerPingPong(cricket::ProtocolType protocol_type) { + void TestTurnAlternateServerPingPong(ProtocolType protocol_type) { std::vector redirect_addresses; redirect_addresses.push_back(kTurnAlternateIntAddr); redirect_addresses.push_back(kTurnIntAddr); - cricket::TestTurnRedirector redirector(redirect_addresses); + TestTurnRedirector redirector(redirect_addresses); turn_server_.AddInternalSocket(kTurnIntAddr, protocol_type); turn_server_.AddInternalSocket(kTurnAlternateIntAddr, protocol_type); turn_server_.set_redirect_hook(&redirector); CreateTurnPort(kTurnUsername, kTurnPassword, - cricket::ProtocolAddress(kTurnIntAddr, protocol_type)); + ProtocolAddress(kTurnIntAddr, protocol_type)); turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_error_, kTimeout); + // Extra round trip due to "use alternate server" error response. + EXPECT_TRUE_SIMULATED_WAIT( + turn_error_, + (protocol_type == PROTO_TCP ? kSimulatedRtt * 4 : kSimulatedRtt * 3), + fake_clock_); ASSERT_EQ(0U, turn_port_->Candidates().size()); rtc::SocketAddress address; // Verify that we have exhausted all alternate servers instead of @@ -387,35 +419,38 @@ class TurnPortTest : public testing::Test, EXPECT_FALSE(redirector.ShouldRedirect(address, &address)); } - void TestTurnAlternateServerDetectRepetition( - cricket::ProtocolType protocol_type) { + void TestTurnAlternateServerDetectRepetition(ProtocolType protocol_type) { std::vector redirect_addresses; redirect_addresses.push_back(kTurnAlternateIntAddr); redirect_addresses.push_back(kTurnAlternateIntAddr); - cricket::TestTurnRedirector redirector(redirect_addresses); + TestTurnRedirector redirector(redirect_addresses); turn_server_.AddInternalSocket(kTurnIntAddr, protocol_type); turn_server_.AddInternalSocket(kTurnAlternateIntAddr, protocol_type); turn_server_.set_redirect_hook(&redirector); CreateTurnPort(kTurnUsername, kTurnPassword, - cricket::ProtocolAddress(kTurnIntAddr, protocol_type)); + ProtocolAddress(kTurnIntAddr, protocol_type)); turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_error_, kTimeout); + // Extra round trip due to "use alternate server" error response. + EXPECT_TRUE_SIMULATED_WAIT( + turn_error_, + (protocol_type == PROTO_TCP ? kSimulatedRtt * 4 : kSimulatedRtt * 3), + fake_clock_); ASSERT_EQ(0U, turn_port_->Candidates().size()); } - void TestTurnConnection() { + void TestTurnConnection(ProtocolType protocol_type) { // Create ports and prepare addresses. - PrepareTurnAndUdpPorts(); + PrepareTurnAndUdpPorts(protocol_type); // Send ping from UDP to TURN. Connection* conn1 = udp_port_->CreateConnection( turn_port_->Candidates()[0], Port::ORIGIN_MESSAGE); ASSERT_TRUE(conn1 != NULL); conn1->Ping(0); - WAIT(!turn_unknown_address_, kTimeout); + SIMULATED_WAIT(!turn_unknown_address_, kSimulatedRtt * 2, fake_clock_); EXPECT_FALSE(turn_unknown_address_); EXPECT_FALSE(conn1->receiving()); EXPECT_EQ(Connection::STATE_WRITE_INIT, conn1->write_state()); @@ -424,22 +459,26 @@ class TurnPortTest : public testing::Test, Connection* conn2 = turn_port_->CreateConnection( udp_port_->Candidates()[0], Port::ORIGIN_MESSAGE); ASSERT_TRUE(conn2 != NULL); - ASSERT_TRUE_WAIT(turn_create_permission_success_, kTimeout); + ASSERT_TRUE_SIMULATED_WAIT(turn_create_permission_success_, kSimulatedRtt, + fake_clock_); conn2->Ping(0); - EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, conn2->write_state(), kTimeout); + // Two hops from TURN port to UDP port through TURN server, thus two RTTs. + EXPECT_EQ_SIMULATED_WAIT(Connection::STATE_WRITABLE, conn2->write_state(), + kSimulatedRtt * 2, fake_clock_); EXPECT_TRUE(conn1->receiving()); EXPECT_TRUE(conn2->receiving()); EXPECT_EQ(Connection::STATE_WRITE_INIT, conn1->write_state()); // Send another ping from UDP to TURN. conn1->Ping(0); - EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, conn1->write_state(), kTimeout); + EXPECT_EQ_SIMULATED_WAIT(Connection::STATE_WRITABLE, conn1->write_state(), + kSimulatedRtt * 2, fake_clock_); EXPECT_TRUE(conn2->receiving()); } void TestDestroyTurnConnection() { - PrepareTurnAndUdpPorts(); + PrepareTurnAndUdpPorts(PROTO_UDP); // Create connections on both ends. Connection* conn1 = udp_port_->CreateConnection(turn_port_->Candidates()[0], @@ -447,34 +486,39 @@ class TurnPortTest : public testing::Test, Connection* conn2 = turn_port_->CreateConnection(udp_port_->Candidates()[0], Port::ORIGIN_MESSAGE); ASSERT_TRUE(conn2 != NULL); - ASSERT_TRUE_WAIT(turn_create_permission_success_, kTimeout); + ASSERT_TRUE_SIMULATED_WAIT(turn_create_permission_success_, kSimulatedRtt, + fake_clock_); // Make sure turn connection can receive. conn1->Ping(0); - EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, conn1->write_state(), kTimeout); + EXPECT_EQ_SIMULATED_WAIT(Connection::STATE_WRITABLE, conn1->write_state(), + kSimulatedRtt * 2, fake_clock_); EXPECT_FALSE(turn_unknown_address_); - // Destroy the connection on the turn port. The TurnEntry is still - // there. So the turn port gets ping from unknown address if it is pinged. + // Destroy the connection on the TURN port. The TurnEntry still exists, so + // the TURN port should still process a ping from an unknown address. conn2->Destroy(); conn1->Ping(0); - EXPECT_TRUE_WAIT(turn_unknown_address_, kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(turn_unknown_address_, kSimulatedRtt, + fake_clock_); // Flush all requests in the invoker to destroy the TurnEntry. - // However, the TURN port should still signal the unknown address. + // Expect that it still processes an incoming ping and signals the + // unknown address. turn_unknown_address_ = false; turn_port_->invoker()->Flush(rtc::Thread::Current()); conn1->Ping(0); - EXPECT_TRUE_WAIT(turn_unknown_address_, kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(turn_unknown_address_, kSimulatedRtt, + fake_clock_); // If the connection is created again, it will start to receive pings. conn2 = turn_port_->CreateConnection(udp_port_->Candidates()[0], Port::ORIGIN_MESSAGE); conn1->Ping(0); - EXPECT_TRUE_WAIT(conn2->receiving(), kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(conn2->receiving(), kSimulatedRtt, fake_clock_); } - void TestTurnSendData() { - PrepareTurnAndUdpPorts(); + void TestTurnSendData(ProtocolType protocol_type) { + PrepareTurnAndUdpPorts(protocol_type); // Create connections and send pings. Connection* conn1 = turn_port_->CreateConnection( @@ -488,9 +532,11 @@ class TurnPortTest : public testing::Test, conn2->SignalReadPacket.connect(static_cast(this), &TurnPortTest::OnUdpReadPacket); conn1->Ping(0); - EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, conn1->write_state(), kTimeout); + EXPECT_EQ_SIMULATED_WAIT(Connection::STATE_WRITABLE, conn1->write_state(), + kSimulatedRtt * 2, fake_clock_); conn2->Ping(0); - EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, conn2->write_state(), kTimeout); + EXPECT_EQ_SIMULATED_WAIT(Connection::STATE_WRITABLE, conn2->write_state(), + kSimulatedRtt * 2, fake_clock_); // Send some data. size_t num_packets = 256; @@ -501,12 +547,12 @@ class TurnPortTest : public testing::Test, } conn1->Send(buf, i + 1, options); conn2->Send(buf, i + 1, options); - main_->ProcessMessages(0); + SIMULATED_WAIT(false, kSimulatedRtt, fake_clock_); } // Check the data. - ASSERT_EQ_WAIT(num_packets, turn_packets_.size(), kTimeout); - ASSERT_EQ_WAIT(num_packets, udp_packets_.size(), kTimeout); + ASSERT_EQ(num_packets, turn_packets_.size()); + ASSERT_EQ(num_packets, udp_packets_.size()); for (size_t i = 0; i < num_packets; ++i) { EXPECT_EQ(i + 1, turn_packets_[i].size()); EXPECT_EQ(i + 1, udp_packets_[i].size()); @@ -515,6 +561,7 @@ class TurnPortTest : public testing::Test, } protected: + rtc::ScopedFakeClock fake_clock_; rtc::Thread* main_; std::unique_ptr pss_; std::unique_ptr ss_; @@ -522,7 +569,7 @@ class TurnPortTest : public testing::Test, rtc::Network network_; rtc::BasicPacketSocketFactory socket_factory_; std::unique_ptr socket_; - cricket::TestTurnServer turn_server_; + TestTurnServer turn_server_; std::unique_ptr turn_port_; std::unique_ptr udp_port_; bool turn_ready_; @@ -542,7 +589,7 @@ TEST_F(TurnPortTest, TestTurnAllocate) { CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr); EXPECT_EQ(0, turn_port_->SetOption(rtc::Socket::OPT_SNDBUF, 10*1024)); turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_ready_, kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 2, fake_clock_); ASSERT_EQ(1U, turn_port_->Candidates().size()); EXPECT_EQ(kTurnUdpExtAddr.ipaddr(), turn_port_->Candidates()[0].address().ipaddr()); @@ -551,11 +598,11 @@ TEST_F(TurnPortTest, TestTurnAllocate) { // Testing a normal UDP allocation using TCP connection. TEST_F(TurnPortTest, TestTurnTcpAllocate) { - turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP); + turn_server_.AddInternalSocket(kTurnTcpIntAddr, PROTO_TCP); CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr); EXPECT_EQ(0, turn_port_->SetOption(rtc::Socket::OPT_SNDBUF, 10*1024)); turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_ready_, kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 3, fake_clock_); ASSERT_EQ(1U, turn_port_->Candidates().size()); EXPECT_EQ(kTurnUdpExtAddr.ipaddr(), turn_port_->Candidates()[0].address().ipaddr()); @@ -566,12 +613,12 @@ TEST_F(TurnPortTest, TestTurnTcpAllocate) { // instead the address that TurnPort originally bound to. The candidate pair // impacted by this behavior should still be used. TEST_F(TurnPortTest, TestTurnTcpAllocationWhenProxyChangesAddressToLocalHost) { - turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP); + turn_server_.AddInternalSocket(kTurnTcpIntAddr, PROTO_TCP); CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr); EXPECT_EQ(0, turn_port_->SetOption(rtc::Socket::OPT_SNDBUF, 10 * 1024)); turn_port_->PrepareAddress(); ConnectSignalAddressReadyToSetLocalhostAsAltenertativeLocalAddress(); - EXPECT_TRUE_WAIT(turn_ready_, kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 3, fake_clock_); ASSERT_EQ(1U, turn_port_->Candidates().size()); EXPECT_EQ(kTurnUdpExtAddr.ipaddr(), turn_port_->Candidates()[0].address().ipaddr()); @@ -580,13 +627,13 @@ TEST_F(TurnPortTest, TestTurnTcpAllocationWhenProxyChangesAddressToLocalHost) { // Testing turn port will attempt to create TCP socket on address resolution // failure. -TEST_F(TurnPortTest, DISABLED_TestTurnTcpOnAddressResolveFailure) { - turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP); - CreateTurnPort(kTurnUsername, kTurnPassword, cricket::ProtocolAddress( - rtc::SocketAddress("www.webrtc-blah-blah.com", 3478), - cricket::PROTO_TCP)); +TEST_F(TurnPortTest, TestTurnTcpOnAddressResolveFailure) { + turn_server_.AddInternalSocket(kTurnTcpIntAddr, PROTO_TCP); + CreateTurnPort(kTurnUsername, kTurnPassword, + ProtocolAddress(rtc::SocketAddress("www.google.invalid", 3478), + PROTO_TCP)); turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_error_, kTimeout); + EXPECT_TRUE_WAIT(turn_error_, kResolverTimeout); // As VSS doesn't provide a DNS resolution, name resolve will fail. TurnPort // will proceed in creating a TCP socket which will fail as there is no // server on the above domain and error will be set to SOCKET_ERROR. @@ -595,12 +642,12 @@ TEST_F(TurnPortTest, DISABLED_TestTurnTcpOnAddressResolveFailure) { // In case of UDP on address resolve failure, TurnPort will not create socket // and return allocate failure. -TEST_F(TurnPortTest, DISABLED_TestTurnUdpOnAddressResolveFailure) { - CreateTurnPort(kTurnUsername, kTurnPassword, cricket::ProtocolAddress( - rtc::SocketAddress("www.webrtc-blah-blah.com", 3478), - cricket::PROTO_UDP)); +TEST_F(TurnPortTest, TestTurnUdpOnAddressResolveFailure) { + CreateTurnPort(kTurnUsername, kTurnPassword, + ProtocolAddress(rtc::SocketAddress("www.google.invalid", 3478), + PROTO_UDP)); turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_error_, kTimeout); + EXPECT_TRUE_WAIT(turn_error_, kResolverTimeout); // Error from turn port will not be socket error. EXPECT_NE(SOCKET_ERROR, turn_port_->error()); } @@ -609,7 +656,7 @@ TEST_F(TurnPortTest, DISABLED_TestTurnUdpOnAddressResolveFailure) { TEST_F(TurnPortTest, TestTurnAllocateBadPassword) { CreateTurnPort(kTurnUsername, "bad", kTurnUdpProtoAddr); turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_error_, kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(turn_error_, kSimulatedRtt * 2, fake_clock_); ASSERT_EQ(0U, turn_port_->Candidates().size()); } @@ -619,13 +666,13 @@ TEST_F(TurnPortTest, TestTurnAllocateNonceResetAfterAllocateMismatch) { // Do a normal allocation first. CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr); turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_ready_, kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 2, fake_clock_); rtc::SocketAddress first_addr(turn_port_->socket()->GetLocalAddress()); // Destroy the turnport while keeping the drop probability to 1 to // suppress the release of the allocation at the server. ss_->set_drop_probability(1.0); turn_port_.reset(); - rtc::Thread::Current()->ProcessMessages(0); + SIMULATED_WAIT(false, kSimulatedRtt, fake_clock_); ss_->set_drop_probability(0.0); // Force the socket server to assign the same port. @@ -642,7 +689,10 @@ TEST_F(TurnPortTest, TestTurnAllocateNonceResetAfterAllocateMismatch) { turn_server_.server()->SetTimestampForNextNonce(ts_before); turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_ready_, kTimeout); + // Four round trips; first we'll get "stale nonce", then + // "allocate mismatch", then "stale nonce" again, then finally it will + // succeed. + EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 4, fake_clock_); EXPECT_NE(first_nonce, turn_port_->nonce()); } @@ -652,7 +702,7 @@ TEST_F(TurnPortTest, TestTurnAllocateMismatch) { // Do a normal allocation first. CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr); turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_ready_, kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 2, fake_clock_); rtc::SocketAddress first_addr(turn_port_->socket()->GetLocalAddress()); // Clear connected_ flag on turnport to suppress the release of @@ -669,7 +719,10 @@ TEST_F(TurnPortTest, TestTurnAllocateMismatch) { // Verifies that the new port has the same address. EXPECT_EQ(first_addr, turn_port_->socket()->GetLocalAddress()); - EXPECT_TRUE_WAIT(turn_ready_, kTimeout); + // Four round trips; first we'll get "stale nonce", then + // "allocate mismatch", then "stale nonce" again, then finally it will + // succeed. + EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 4, fake_clock_); // Verifies that the new port has a different address now. EXPECT_NE(first_addr, turn_port_->socket()->GetLocalAddress()); @@ -688,7 +741,7 @@ TEST_F(TurnPortTest, TestSharedSocketAllocateMismatch) { // Do a normal allocation first. CreateSharedTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr); turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_ready_, kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 2, fake_clock_); rtc::SocketAddress first_addr(turn_port_->socket()->GetLocalAddress()); // Clear connected_ flag on turnport to suppress the release of @@ -703,7 +756,8 @@ TEST_F(TurnPortTest, TestSharedSocketAllocateMismatch) { EXPECT_TRUE(turn_port_->SharedSocket()); turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_ready_, kTimeout); + // Extra 2 round trips due to allocate mismatch. + EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 4, fake_clock_); // Verifies that the new port has a different address now. EXPECT_NE(first_addr, turn_port_->socket()->GetLocalAddress()); @@ -711,12 +765,12 @@ TEST_F(TurnPortTest, TestSharedSocketAllocateMismatch) { } TEST_F(TurnPortTest, TestTurnTcpAllocateMismatch) { - turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP); + turn_server_.AddInternalSocket(kTurnTcpIntAddr, PROTO_TCP); CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr); // Do a normal allocation first. turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_ready_, kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 3, fake_clock_); rtc::SocketAddress first_addr(turn_port_->socket()->GetLocalAddress()); // Clear connected_ flag on turnport to suppress the release of @@ -733,41 +787,41 @@ TEST_F(TurnPortTest, TestTurnTcpAllocateMismatch) { // Verifies that the new port has the same address. EXPECT_EQ(first_addr, turn_port_->socket()->GetLocalAddress()); - EXPECT_TRUE_WAIT(turn_ready_, kTimeout); + // Extra 2 round trips due to allocate mismatch. + EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 5, fake_clock_); // Verifies that the new port has a different address now. EXPECT_NE(first_addr, turn_port_->socket()->GetLocalAddress()); } TEST_F(TurnPortTest, TestRefreshRequestGetsErrorResponse) { - rtc::ScopedFakeClock clock; CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr); - PrepareTurnAndUdpPorts(); + PrepareTurnAndUdpPorts(PROTO_UDP); turn_port_->CreateConnection(udp_port_->Candidates()[0], Port::ORIGIN_MESSAGE); // Set bad credentials. - cricket::RelayCredentials bad_credentials("bad_user", "bad_pwd"); + RelayCredentials bad_credentials("bad_user", "bad_pwd"); turn_port_->set_credentials(bad_credentials); turn_refresh_success_ = false; // This sends out the first RefreshRequest with correct credentials. // When this succeeds, it will schedule a new RefreshRequest with the bad // credential. - turn_port_->FlushRequests(cricket::TURN_REFRESH_REQUEST); - EXPECT_TRUE_SIMULATED_WAIT(turn_refresh_success_, kTimeout, clock); + turn_port_->FlushRequests(TURN_REFRESH_REQUEST); + EXPECT_TRUE_SIMULATED_WAIT(turn_refresh_success_, kSimulatedRtt, fake_clock_); // Flush it again, it will receive a bad response. - turn_port_->FlushRequests(cricket::TURN_REFRESH_REQUEST); - EXPECT_TRUE_SIMULATED_WAIT(!turn_refresh_success_, kTimeout, clock); - EXPECT_TRUE_SIMULATED_WAIT(!turn_port_->connected(), kTimeout, clock); - EXPECT_TRUE_SIMULATED_WAIT(CheckAllConnectionsFailedAndPruned(), kTimeout, - clock); - EXPECT_TRUE_SIMULATED_WAIT(!turn_port_->HasRequests(), kTimeout, clock); + turn_port_->FlushRequests(TURN_REFRESH_REQUEST); + EXPECT_TRUE_SIMULATED_WAIT(!turn_refresh_success_, kSimulatedRtt, + fake_clock_); + EXPECT_FALSE(turn_port_->connected()); + EXPECT_TRUE(CheckAllConnectionsFailedAndPruned()); + EXPECT_FALSE(turn_port_->HasRequests()); } // Test that TurnPort will not handle any incoming packets once it has been // closed. TEST_F(TurnPortTest, TestStopProcessingPacketsAfterClosed) { CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr); - PrepareTurnAndUdpPorts(); + PrepareTurnAndUdpPorts(PROTO_UDP); Connection* conn1 = turn_port_->CreateConnection(udp_port_->Candidates()[0], Port::ORIGIN_MESSAGE); Connection* conn2 = udp_port_->CreateConnection(turn_port_->Candidates()[0], @@ -776,13 +830,14 @@ TEST_F(TurnPortTest, TestStopProcessingPacketsAfterClosed) { ASSERT_TRUE(conn2 != NULL); // Make sure conn2 is writable. conn2->Ping(0); - EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, conn2->write_state(), kTimeout); + EXPECT_EQ_SIMULATED_WAIT(Connection::STATE_WRITABLE, conn2->write_state(), + kSimulatedRtt * 2, fake_clock_); turn_port_->Close(); - rtc::Thread::Current()->ProcessMessages(0); + SIMULATED_WAIT(false, kSimulatedRtt, fake_clock_); turn_unknown_address_ = false; conn2->Ping(0); - rtc::Thread::Current()->ProcessMessages(500); + SIMULATED_WAIT(false, kSimulatedRtt, fake_clock_); // Since the turn port does not handle packets any more, it should not // SignalUnknownAddress. EXPECT_FALSE(turn_unknown_address_); @@ -790,9 +845,9 @@ TEST_F(TurnPortTest, TestStopProcessingPacketsAfterClosed) { // Test that CreateConnection will return null if port becomes disconnected. TEST_F(TurnPortTest, TestCreateConnectionWhenSocketClosed) { - turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP); + turn_server_.AddInternalSocket(kTurnTcpIntAddr, PROTO_TCP); CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr); - PrepareTurnAndUdpPorts(); + PrepareTurnAndUdpPorts(PROTO_TCP); // Create a connection. Connection* conn1 = turn_port_->CreateConnection(udp_port_->Candidates()[0], Port::ORIGIN_MESSAGE); @@ -808,52 +863,53 @@ TEST_F(TurnPortTest, TestCreateConnectionWhenSocketClosed) { // Tests that when a TCP socket is closed, the respective TURN connection will // be destroyed. TEST_F(TurnPortTest, TestSocketCloseWillDestroyConnection) { - turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP); + turn_server_.AddInternalSocket(kTurnTcpIntAddr, PROTO_TCP); CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr); - PrepareTurnAndUdpPorts(); + PrepareTurnAndUdpPorts(PROTO_TCP); Connection* conn = turn_port_->CreateConnection(udp_port_->Candidates()[0], Port::ORIGIN_MESSAGE); EXPECT_NE(nullptr, conn); EXPECT_TRUE(!turn_port_->connections().empty()); turn_port_->socket()->SignalClose(turn_port_->socket(), 1); - EXPECT_TRUE_WAIT(turn_port_->connections().empty(), kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(turn_port_->connections().empty(), + kConnectionDestructionDelay, fake_clock_); } // Test try-alternate-server feature. TEST_F(TurnPortTest, TestTurnAlternateServerUDP) { - TestTurnAlternateServer(cricket::PROTO_UDP); + TestTurnAlternateServer(PROTO_UDP); } TEST_F(TurnPortTest, TestTurnAlternateServerTCP) { - TestTurnAlternateServer(cricket::PROTO_TCP); + TestTurnAlternateServer(PROTO_TCP); } // Test that we fail when we redirect to an address different from // current IP family. TEST_F(TurnPortTest, TestTurnAlternateServerV4toV6UDP) { - TestTurnAlternateServerV4toV6(cricket::PROTO_UDP); + TestTurnAlternateServerV4toV6(PROTO_UDP); } TEST_F(TurnPortTest, TestTurnAlternateServerV4toV6TCP) { - TestTurnAlternateServerV4toV6(cricket::PROTO_TCP); + TestTurnAlternateServerV4toV6(PROTO_TCP); } // Test try-alternate-server catches the case of pingpong. TEST_F(TurnPortTest, TestTurnAlternateServerPingPongUDP) { - TestTurnAlternateServerPingPong(cricket::PROTO_UDP); + TestTurnAlternateServerPingPong(PROTO_UDP); } TEST_F(TurnPortTest, TestTurnAlternateServerPingPongTCP) { - TestTurnAlternateServerPingPong(cricket::PROTO_TCP); + TestTurnAlternateServerPingPong(PROTO_TCP); } // Test try-alternate-server catch the case of repeated server. TEST_F(TurnPortTest, TestTurnAlternateServerDetectRepetitionUDP) { - TestTurnAlternateServerDetectRepetition(cricket::PROTO_UDP); + TestTurnAlternateServerDetectRepetition(PROTO_UDP); } TEST_F(TurnPortTest, TestTurnAlternateServerDetectRepetitionTCP) { - TestTurnAlternateServerDetectRepetition(cricket::PROTO_TCP); + TestTurnAlternateServerDetectRepetition(PROTO_TCP); } // Do a TURN allocation and try to send a packet to it from the outside. @@ -862,20 +918,20 @@ TEST_F(TurnPortTest, TestTurnAlternateServerDetectRepetitionTCP) { // outside. It should now work as well. TEST_F(TurnPortTest, TestTurnConnection) { CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr); - TestTurnConnection(); + TestTurnConnection(PROTO_UDP); } // Similar to above, except that this test will use the shared socket. TEST_F(TurnPortTest, TestTurnConnectionUsingSharedSocket) { CreateSharedTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr); - TestTurnConnection(); + TestTurnConnection(PROTO_UDP); } // Test that we can establish a TCP connection with TURN server. TEST_F(TurnPortTest, TestTurnTcpConnection) { - turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP); + turn_server_.AddInternalSocket(kTurnTcpIntAddr, PROTO_TCP); CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr); - TestTurnConnection(); + TestTurnConnection(PROTO_TCP); } // Test that if a connection on a TURN port is destroyed, the TURN port can @@ -895,12 +951,11 @@ TEST_F(TurnPortTest, TestDestroyTurnConnectionUsingSharedSocket) { // Test that we fail to create a connection when we want to use TLS over TCP. // This test should be removed once we have TLS support. TEST_F(TurnPortTest, TestTurnTlsTcpConnectionFails) { - cricket::ProtocolAddress secure_addr(kTurnTcpProtoAddr.address, - kTurnTcpProtoAddr.proto, - true); + ProtocolAddress secure_addr(kTurnTcpProtoAddr.address, + kTurnTcpProtoAddr.proto, true); CreateTurnPort(kTurnUsername, kTurnPassword, secure_addr); turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_error_, kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(turn_error_, kSimulatedRtt * 2, fake_clock_); ASSERT_EQ(0U, turn_port_->Candidates().size()); } @@ -910,7 +965,7 @@ TEST_F(TurnPortTest, TestTurnTlsTcpConnectionFails) { TEST_F(TurnPortTest, TestTurnConnectionUsingOTUNonce) { turn_server_.set_enable_otu_nonce(true); CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr); - TestTurnConnection(); + TestTurnConnection(PROTO_UDP); } // Test that CreatePermissionRequest will be scheduled after the success @@ -918,30 +973,32 @@ TEST_F(TurnPortTest, TestTurnConnectionUsingOTUNonce) { // ErrorResponse if the ufrag and pwd are incorrect. TEST_F(TurnPortTest, TestRefreshCreatePermissionRequest) { CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr); - PrepareTurnAndUdpPorts(); + PrepareTurnAndUdpPorts(PROTO_UDP); Connection* conn = turn_port_->CreateConnection(udp_port_->Candidates()[0], Port::ORIGIN_MESSAGE); ASSERT_TRUE(conn != NULL); - EXPECT_TRUE_WAIT(turn_create_permission_success_, kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(turn_create_permission_success_, kSimulatedRtt, + fake_clock_); turn_create_permission_success_ = false; // A create-permission-request should be pending. // After the next create-permission-response is received, it will schedule // another request with bad_ufrag and bad_pwd. - cricket::RelayCredentials bad_credentials("bad_user", "bad_pwd"); + RelayCredentials bad_credentials("bad_user", "bad_pwd"); turn_port_->set_credentials(bad_credentials); - turn_port_->FlushRequests(cricket::kAllRequests); - EXPECT_TRUE_WAIT(turn_create_permission_success_, kTimeout); + turn_port_->FlushRequests(kAllRequests); + EXPECT_TRUE_SIMULATED_WAIT(turn_create_permission_success_, kSimulatedRtt, + fake_clock_); // Flush the requests again; the create-permission-request will fail. - turn_port_->FlushRequests(cricket::kAllRequests); - EXPECT_TRUE_WAIT(!turn_create_permission_success_, kTimeout); - EXPECT_TRUE_WAIT(CheckConnectionFailedAndPruned(conn), kTimeout); + turn_port_->FlushRequests(kAllRequests); + EXPECT_TRUE_SIMULATED_WAIT(!turn_create_permission_success_, kSimulatedRtt, + fake_clock_); + EXPECT_TRUE(CheckConnectionFailedAndPruned(conn)); } TEST_F(TurnPortTest, TestChannelBindGetErrorResponse) { - rtc::ScopedFakeClock clock; CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr); - PrepareTurnAndUdpPorts(); + PrepareTurnAndUdpPorts(PROTO_UDP); Connection* conn1 = turn_port_->CreateConnection(udp_port_->Candidates()[0], Port::ORIGIN_MESSAGE); ASSERT_TRUE(conn1 != nullptr); @@ -950,21 +1007,23 @@ TEST_F(TurnPortTest, TestChannelBindGetErrorResponse) { ASSERT_TRUE(conn2 != nullptr); conn1->Ping(0); - EXPECT_TRUE_SIMULATED_WAIT(conn1->writable(), kTimeout, clock); - bool success = - turn_port_->SetEntryChannelId(udp_port_->Candidates()[0].address(), -1); - ASSERT_TRUE(success); + EXPECT_TRUE_SIMULATED_WAIT(conn1->writable(), kSimulatedRtt * 2, fake_clock_); + // TODO(deadbeef): SetEntryChannelId should not be a public method. + // Instead we should set an option on the fake TURN server to force it to + // send a channel bind errors. + ASSERT_TRUE( + turn_port_->SetEntryChannelId(udp_port_->Candidates()[0].address(), -1)); std::string data = "ABC"; conn1->Send(data.data(), data.length(), options); - EXPECT_TRUE_SIMULATED_WAIT(CheckConnectionFailedAndPruned(conn1), kTimeout, - clock); + EXPECT_TRUE_SIMULATED_WAIT(CheckConnectionFailedAndPruned(conn1), + kSimulatedRtt, fake_clock_); // Verify that no packet can be sent after a bind request error. conn2->SignalReadPacket.connect(static_cast(this), &TurnPortTest::OnUdpReadPacket); conn1->Send(data.data(), data.length(), options); - SIMULATED_WAIT(!udp_packets_.empty(), kTimeout, clock); + SIMULATED_WAIT(!udp_packets_.empty(), kSimulatedRtt, fake_clock_); EXPECT_TRUE(udp_packets_.empty()); } @@ -972,29 +1031,27 @@ TEST_F(TurnPortTest, TestChannelBindGetErrorResponse) { TEST_F(TurnPortTest, TestTurnSendDataTurnUdpToUdp) { // Create ports and prepare addresses. CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr); - TestTurnSendData(); - EXPECT_EQ(cricket::UDP_PROTOCOL_NAME, - turn_port_->Candidates()[0].relay_protocol()); + TestTurnSendData(PROTO_UDP); + EXPECT_EQ(UDP_PROTOCOL_NAME, turn_port_->Candidates()[0].relay_protocol()); } // Do a TURN allocation, establish a TCP connection, and send some data. TEST_F(TurnPortTest, TestTurnSendDataTurnTcpToUdp) { - turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP); + turn_server_.AddInternalSocket(kTurnTcpIntAddr, PROTO_TCP); // Create ports and prepare addresses. CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr); - TestTurnSendData(); - EXPECT_EQ(cricket::TCP_PROTOCOL_NAME, - turn_port_->Candidates()[0].relay_protocol()); + TestTurnSendData(PROTO_TCP); + EXPECT_EQ(TCP_PROTOCOL_NAME, turn_port_->Candidates()[0].relay_protocol()); } // Test TURN fails to make a connection from IPv6 address to a server which has // IPv4 address. TEST_F(TurnPortTest, TestTurnLocalIPv6AddressServerIPv4) { - turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, cricket::PROTO_UDP); + turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, PROTO_UDP); CreateTurnPort(kLocalIPv6Addr, kTurnUsername, kTurnPassword, kTurnUdpProtoAddr); turn_port_->PrepareAddress(); - ASSERT_TRUE_WAIT(turn_error_, kTimeout); + ASSERT_TRUE_SIMULATED_WAIT(turn_error_, kSimulatedRtt, fake_clock_); EXPECT_TRUE(turn_port_->Candidates().empty()); } @@ -1002,11 +1059,11 @@ TEST_F(TurnPortTest, TestTurnLocalIPv6AddressServerIPv4) { // IPv6 intenal address. But in this test external address is a IPv4 address, // hence allocated address will be a IPv4 address. TEST_F(TurnPortTest, TestTurnLocalIPv6AddressServerIPv6ExtenalIPv4) { - turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, cricket::PROTO_UDP); + turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, PROTO_UDP); CreateTurnPort(kLocalIPv6Addr, kTurnUsername, kTurnPassword, kTurnUdpIPv6ProtoAddr); turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_ready_, kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 2, fake_clock_); ASSERT_EQ(1U, turn_port_->Candidates().size()); EXPECT_EQ(kTurnUdpExtAddr.ipaddr(), turn_port_->Candidates()[0].address().ipaddr()); @@ -1018,18 +1075,17 @@ TEST_F(TurnPortTest, TestTurnLocalIPv6AddressServerIPv6ExtenalIPv4) { // its local candidate will still be an IPv4 address and it can only create // connections with IPv4 remote candidates. TEST_F(TurnPortTest, TestCandidateAddressFamilyMatch) { - turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, cricket::PROTO_UDP); + turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, PROTO_UDP); CreateTurnPort(kLocalIPv6Addr, kTurnUsername, kTurnPassword, kTurnUdpIPv6ProtoAddr); turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_ready_, kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 2, fake_clock_); ASSERT_EQ(1U, turn_port_->Candidates().size()); // Create an IPv4 candidate. It will match the TURN candidate. - cricket::Candidate remote_candidate(cricket::ICE_CANDIDATE_COMPONENT_RTP, - "udp", kLocalAddr2, 0, "", "", "local", 0, - kCandidateFoundation); + Candidate remote_candidate(ICE_CANDIDATE_COMPONENT_RTP, "udp", kLocalAddr2, 0, + "", "", "local", 0, kCandidateFoundation); remote_candidate.set_address(kLocalAddr2); Connection* conn = turn_port_->CreateConnection(remote_candidate, Port::ORIGIN_MESSAGE); @@ -1046,7 +1102,7 @@ TEST_F(TurnPortTest, TestOriginHeader) { CreateTurnPortWithOrigin(kLocalAddr1, kTurnUsername, kTurnPassword, kTurnUdpProtoAddr, kTestOrigin); turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_ready_, kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 2, fake_clock_); ASSERT_GT(turn_server_.server()->allocations().size(), 0U); SocketAddress local_address = turn_port_->GetLocalAddress(); ASSERT_TRUE(turn_server_.FindAllocation(local_address) != NULL); @@ -1055,18 +1111,16 @@ TEST_F(TurnPortTest, TestOriginHeader) { // Test that a CreatePermission failure will result in the connection being // pruned and failed. -TEST_F(TurnPortTest, TestConnectionFaildAndPrunedOnCreatePermissionFailure) { - rtc::ScopedFakeClock clock; - SIMULATED_WAIT(false, 101, clock); - turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP); +TEST_F(TurnPortTest, TestConnectionFailedAndPrunedOnCreatePermissionFailure) { + turn_server_.AddInternalSocket(kTurnTcpIntAddr, PROTO_TCP); turn_server_.server()->set_reject_private_addresses(true); CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr); turn_port_->PrepareAddress(); - EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kTimeout, clock); + EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 3, fake_clock_); CreateUdpPort(SocketAddress("10.0.0.10", 0)); udp_port_->PrepareAddress(); - EXPECT_TRUE_SIMULATED_WAIT(udp_ready_, kTimeout, clock); + EXPECT_TRUE_SIMULATED_WAIT(udp_ready_, kSimulatedRtt, fake_clock_); // Create a connection. TestConnectionWrapper conn(turn_port_->CreateConnection( udp_port_->Candidates()[0], Port::ORIGIN_MESSAGE)); @@ -1075,57 +1129,60 @@ TEST_F(TurnPortTest, TestConnectionFaildAndPrunedOnCreatePermissionFailure) { // Asynchronously, CreatePermission request should be sent and fail, which // will make the connection pruned and failed. EXPECT_TRUE_SIMULATED_WAIT(CheckConnectionFailedAndPruned(conn.connection()), - kTimeout, clock); - EXPECT_TRUE_SIMULATED_WAIT(!turn_create_permission_success_, kTimeout, clock); + kSimulatedRtt, fake_clock_); + EXPECT_TRUE_SIMULATED_WAIT(!turn_create_permission_success_, kSimulatedRtt, + fake_clock_); // Check that the connection is not deleted asynchronously. - SIMULATED_WAIT(conn.connection() == nullptr, kTimeout, clock); - EXPECT_TRUE(conn.connection() != nullptr); + SIMULATED_WAIT(conn.connection() == nullptr, kConnectionDestructionDelay, + fake_clock_); + EXPECT_NE(nullptr, conn.connection()); } // Test that a TURN allocation is released when the port is closed. TEST_F(TurnPortTest, TestTurnReleaseAllocation) { CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr); turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_ready_, kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 2, fake_clock_); ASSERT_GT(turn_server_.server()->allocations().size(), 0U); turn_port_.reset(); - EXPECT_EQ_WAIT(0U, turn_server_.server()->allocations().size(), kTimeout); + EXPECT_EQ_SIMULATED_WAIT(0U, turn_server_.server()->allocations().size(), + kSimulatedRtt, fake_clock_); } // Test that a TURN TCP allocation is released when the port is closed. -TEST_F(TurnPortTest, DISABLED_TestTurnTCPReleaseAllocation) { - turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP); +TEST_F(TurnPortTest, TestTurnTCPReleaseAllocation) { + turn_server_.AddInternalSocket(kTurnTcpIntAddr, PROTO_TCP); CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr); turn_port_->PrepareAddress(); - EXPECT_TRUE_WAIT(turn_ready_, kTimeout); + EXPECT_TRUE_SIMULATED_WAIT(turn_ready_, kSimulatedRtt * 3, fake_clock_); ASSERT_GT(turn_server_.server()->allocations().size(), 0U); turn_port_.reset(); - EXPECT_EQ_WAIT(0U, turn_server_.server()->allocations().size(), kTimeout); + EXPECT_EQ_SIMULATED_WAIT(0U, turn_server_.server()->allocations().size(), + kSimulatedRtt, fake_clock_); } // This test verifies any FD's are not leaked after TurnPort is destroyed. // https://code.google.com/p/webrtc/issues/detail?id=2651 #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) -// 1 second is not always enough for getaddrinfo(). -// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5191 -static const unsigned int kResolverTimeout = 10000; TEST_F(TurnPortTest, TestResolverShutdown) { - turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, cricket::PROTO_UDP); + turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, PROTO_UDP); int last_fd_count = GetFDCount(); // Need to supply unresolved address to kick off resolver. CreateTurnPort(kLocalIPv6Addr, kTurnUsername, kTurnPassword, - cricket::ProtocolAddress(rtc::SocketAddress( - "www.google.invalid", 3478), cricket::PROTO_UDP)); + ProtocolAddress(rtc::SocketAddress("www.google.invalid", 3478), + PROTO_UDP)); turn_port_->PrepareAddress(); ASSERT_TRUE_WAIT(turn_error_, kResolverTimeout); EXPECT_TRUE(turn_port_->Candidates().empty()); turn_port_.reset(); rtc::Thread::Current()->Post(RTC_FROM_HERE, this, MSG_TESTFINISH); // Waiting for above message to be processed. - ASSERT_TRUE_WAIT(test_finish_, kTimeout); + ASSERT_TRUE_SIMULATED_WAIT(test_finish_, 1, fake_clock_); EXPECT_EQ(last_fd_count, GetFDCount()); } #endif + +} // namespace cricket diff --git a/webrtc/p2p/base/turnserver.cc b/webrtc/p2p/base/turnserver.cc index 0b06c44ab0..b4510e637f 100644 --- a/webrtc/p2p/base/turnserver.cc +++ b/webrtc/p2p/base/turnserver.cc @@ -509,10 +509,11 @@ void TurnServer::OnAllocationDestroyed(TurnServerAllocation* allocation) { // Removing the internal socket if the connection is not udp. rtc::AsyncPacketSocket* socket = allocation->conn()->socket(); InternalSocketMap::iterator iter = server_sockets_.find(socket); - ASSERT(iter != server_sockets_.end()); // Skip if the socket serving this allocation is UDP, as this will be shared // by all allocations. - if (iter->second != cricket::PROTO_UDP) { + // Note: We may not find a socket if it's a TCP socket that was closed, and + // the allocation is only now timing out. + if (iter != server_sockets_.end() && iter->second != cricket::PROTO_UDP) { DestroyInternalSocket(socket); }