Chromium Code Reviews| Index: webrtc/p2p/base/p2ptransportchannel_unittest.cc |
| diff --git a/webrtc/p2p/base/p2ptransportchannel_unittest.cc b/webrtc/p2p/base/p2ptransportchannel_unittest.cc |
| index d367d269d969dc1eb5270d03ddb96d143d4b44ce..313bdbd3712bfa6ceab33d67135c0a4a848ba777 100644 |
| --- a/webrtc/p2p/base/p2ptransportchannel_unittest.cc |
| +++ b/webrtc/p2p/base/p2ptransportchannel_unittest.cc |
| @@ -54,11 +54,13 @@ static const SocketAddress kPublicAddrs[2] = |
| // IPv6 Addresses on the public internet. |
| static const SocketAddress kIPv6PublicAddrs[2] = { |
| SocketAddress("2400:4030:1:2c00:be30:abcd:efab:cdef", 0), |
| - SocketAddress("2620:0:1000:1b03:2e41:38ff:fea6:f2a4", 0) |
| -}; |
| + SocketAddress("2600:0:1000:1b03:2e41:38ff:fea6:f2a4", 0)}; |
| // For configuring multihomed clients. |
| static const SocketAddress kAlternateAddrs[2] = { |
| SocketAddress("101.101.101.101", 0), SocketAddress("202.202.202.202", 0)}; |
| +static const SocketAddress kIPv6AlternateAddrs[2] = { |
| + SocketAddress("2401:4030:1:2c00:be30:abcd:efab:cdef", 0), |
| + SocketAddress("2601:0:1000:1b03:2e41:38ff:fea6:f2a4", 0)}; |
| // Addresses for HTTP proxy servers. |
| static const SocketAddress kHttpsProxyAddrs[2] = |
| { SocketAddress("11.11.11.1", 443), SocketAddress("22.22.22.1", 443) }; |
| @@ -427,7 +429,7 @@ class P2PTransportChannelTestBase : public testing::Test, |
| return NULL; |
| } |
| } |
| - PortAllocator* GetAllocator(int endpoint) { |
| + BasicPortAllocator* GetAllocator(int endpoint) { |
| return GetEndpoint(endpoint)->allocator_.get(); |
| } |
| webrtc::FakeMetricsObserver* GetMetricsObserver(int endpoint) { |
| @@ -2062,10 +2064,10 @@ TEST_F(P2PTransportChannelSameNatTest, TestConesBehindSameCone) { |
| // interfaces, so that we can simulate a user with Ethernet and VPN networks. |
| class P2PTransportChannelMultihomedTest : public P2PTransportChannelTestBase { |
| public: |
| - const cricket::Connection* GetConnectionWithRemoteAddress( |
| - cricket::P2PTransportChannel* channel, |
| + const Connection* GetConnectionWithRemoteAddress( |
| + P2PTransportChannel* channel, |
| const SocketAddress& address) { |
| - for (cricket::Connection* conn : channel->connections()) { |
| + for (Connection* conn : channel->connections()) { |
| if (conn->remote_candidate().address().EqualIPs(address)) { |
| return conn; |
| } |
| @@ -2073,10 +2075,9 @@ class P2PTransportChannelMultihomedTest : public P2PTransportChannelTestBase { |
| return nullptr; |
| } |
| - cricket::Connection* GetConnectionWithLocalAddress( |
| - cricket::P2PTransportChannel* channel, |
| - const SocketAddress& address) { |
| - for (cricket::Connection* conn : channel->connections()) { |
| + Connection* GetConnectionWithLocalAddress(P2PTransportChannel* channel, |
| + const SocketAddress& address) { |
| + for (Connection* conn : channel->connections()) { |
| if (conn->local_candidate().address().EqualIPs(address)) { |
| return conn; |
| } |
| @@ -2084,10 +2085,21 @@ class P2PTransportChannelMultihomedTest : public P2PTransportChannelTestBase { |
| return nullptr; |
| } |
| - void DestroyAllButBestConnection(cricket::P2PTransportChannel* channel) { |
| - const cricket::Connection* selected_connection = |
| - channel->selected_connection(); |
| - for (cricket::Connection* conn : channel->connections()) { |
| + Connection* GetConnection(P2PTransportChannel* channel, |
| + const SocketAddress& local, |
| + const SocketAddress& remote) { |
| + for (Connection* conn : channel->connections()) { |
| + if (conn->local_candidate().address().EqualIPs(local) && |
| + conn->remote_candidate().address().EqualIPs(remote)) { |
| + return conn; |
| + } |
| + } |
| + return nullptr; |
| + } |
| + |
| + void DestroyAllButBestConnection(P2PTransportChannel* channel) { |
| + const Connection* selected_connection = channel->selected_connection(); |
| + for (Connection* conn : channel->connections()) { |
| if (conn != selected_connection) { |
| conn->Destroy(); |
| } |
| @@ -2209,6 +2221,99 @@ TEST_F(P2PTransportChannelMultihomedTest, TestFailoverControllingSide) { |
| DestroyChannels(); |
| } |
| +// Tests that we can quickly switch links if an interface goes down when |
| +// there are many connections. |
| +TEST_F(P2PTransportChannelMultihomedTest, TestFailoverWithManyConnections) { |
| + rtc::ScopedFakeClock clock; |
| + test_turn_server()->AddInternalSocket(kTurnTcpIntAddr, PROTO_TCP); |
| + RelayServerConfig turn_server(RELAY_TURN); |
| + turn_server.credentials = kRelayCredentials; |
| + turn_server.ports.push_back( |
| + ProtocolAddress(kTurnTcpIntAddr, PROTO_TCP, false)); |
| + GetAllocator(0)->AddTurnServer(turn_server); |
| + GetAllocator(1)->AddTurnServer(turn_server); |
| + // Enable IPv6 |
| + SetAllocatorFlags(0, PORTALLOCATOR_ENABLE_IPV6); |
| + SetAllocatorFlags(1, PORTALLOCATOR_ENABLE_IPV6); |
| + SetAllocationStepDelay(0, kMinimumStepDelay); |
| + SetAllocationStepDelay(1, kMinimumStepDelay); |
| + |
| + auto& wifi = kPublicAddrs; |
| + auto& cellular = kAlternateAddrs; |
| + auto& wifiIpv6 = kIPv6PublicAddrs; |
| + auto& cellularIpv6 = kIPv6AlternateAddrs; |
| + AddAddress(0, wifi[0], "wifi0", rtc::ADAPTER_TYPE_WIFI); |
| + AddAddress(0, wifiIpv6[0], "wifi0", rtc::ADAPTER_TYPE_WIFI); |
| + AddAddress(0, cellular[0], "cellular0", rtc::ADAPTER_TYPE_CELLULAR); |
| + AddAddress(0, cellularIpv6[0], "cellular0", rtc::ADAPTER_TYPE_CELLULAR); |
| + AddAddress(1, wifi[1], "wifi1", rtc::ADAPTER_TYPE_WIFI); |
| + AddAddress(1, wifiIpv6[1], "wifi1", rtc::ADAPTER_TYPE_WIFI); |
| + AddAddress(1, cellular[1], "cellular1", rtc::ADAPTER_TYPE_CELLULAR); |
| + AddAddress(1, cellularIpv6[1], "cellular1", rtc::ADAPTER_TYPE_CELLULAR); |
| + |
| + // Set smaller delay on the TCP TURN server so that TCP TURN candidates |
| + // will be created in time. |
| + virtual_socket_server()->SetDelayOnAddress(kTurnTcpIntAddr, 1); |
| + virtual_socket_server()->SetDelayOnAddress(kTurnUdpExtAddr, 1); |
| + virtual_socket_server()->set_delay_mean(500); |
| + virtual_socket_server()->UpdateDelayDistribution(); |
| + |
| + // Make the receiving timeout shorter for testing. |
| + IceConfig config = CreateIceConfig(1000, GATHER_CONTINUALLY); |
| + // Create channels and let them go writable, as usual. |
| + CreateChannels(config, config, true /* ice_renomination */); |
| + EXPECT_TRUE_SIMULATED_WAIT(ep1_ch1()->receiving() && ep1_ch1()->writable() && |
| + ep2_ch1()->receiving() && |
| + ep2_ch1()->writable(), |
| + kMediumTimeout, clock); |
| + EXPECT_TRUE_SIMULATED_WAIT( |
| + ep1_ch1()->selected_connection() && ep2_ch1()->selected_connection() && |
| + LocalCandidate(ep1_ch1())->address().EqualIPs(wifiIpv6[0]) && |
| + RemoteCandidate(ep1_ch1())->address().EqualIPs(wifiIpv6[1]), |
| + kMediumTimeout, clock); |
| + |
| + // Blackhole any traffic to or from the wifi on endpoint 1. |
| + LOG(LS_INFO) << "Failing over..."; |
| + fw()->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, wifi[0]); |
| + fw()->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, wifiIpv6[0]); |
| + |
| + // The selected connections may switch, so keep references to them. |
| + const Connection* selected_connection1 = ep1_ch1()->selected_connection(); |
| + const Connection* selected_connection2 = ep2_ch1()->selected_connection(); |
| + EXPECT_TRUE_SIMULATED_WAIT( |
| + !selected_connection1->receiving() && !selected_connection2->receiving(), |
| + kMediumTimeout, clock); |
| + |
| + // Premier connections will be pinged at relatively higher rate when the |
| + // selected connection becomes not receiving. |
| + Connection* premier_connection1 = |
| + GetConnection(ep1_ch1(), cellularIpv6[0], wifiIpv6[1]); |
| + ASSERT_NE(nullptr, premier_connection1); |
| + int64_t last_ping_sent1 = premier_connection1->last_ping_sent(); |
| + int num_pings_sent1 = premier_connection1->num_pings_sent(); |
| + EXPECT_TRUE_SIMULATED_WAIT( |
| + num_pings_sent1 < premier_connection1->num_pings_sent(), kMediumTimeout, |
| + clock); |
| + int64_t ping_interval1 = |
| + (premier_connection1->last_ping_sent() - last_ping_sent1) / |
| + (premier_connection1->num_pings_sent() - num_pings_sent1); |
| + constexpr int SCHEDULING_DELAY = 200; |
| + EXPECT_LT( |
| + ping_interval1, |
| + WEAK_OR_STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL + SCHEDULING_DELAY); |
|
Taylor Brandstetter
2016/10/21 20:18:49
This condition seems a little too specific for thi
honghaiz3
2016/10/21 21:27:26
That would require very similar setup (including m
|
| + |
| + // It should switch over to use the cellular IPv6 addr on endpoint 1 before |
| + // it timed out on writing. |
| + EXPECT_TRUE_SIMULATED_WAIT( |
| + ep1_ch1()->selected_connection()->receiving() && |
| + ep2_ch1()->selected_connection()->receiving() && |
| + RemoteCandidate(ep2_ch1())->address().EqualIPs(cellularIpv6[0]) && |
| + LocalCandidate(ep1_ch1())->address().EqualIPs(cellularIpv6[0]), |
| + kMediumTimeout, clock); |
| + |
| + DestroyChannels(); |
| +} |
| + |
| // Test that when the controlling side switches the selected connection, |
| // the nomination of the selected connection on the controlled side will |
| // increase. |
| @@ -2625,7 +2730,7 @@ TEST_F(P2PTransportChannelMultihomedTest, |
| // Add a new wifi interface on end point 2. We should expect a new connection |
| // to be created and the new one will be the best connection. |
| AddAddress(1, wifi[1], "test_wifi1", rtc::ADAPTER_TYPE_WIFI); |
| - const cricket::Connection* conn; |
| + const Connection* conn; |
| EXPECT_TRUE_WAIT((conn = ep1_ch1()->selected_connection()) != nullptr && |
| conn->remote_candidate().address().EqualIPs(wifi[1]), |
| kDefaultTimeout); |
| @@ -2637,13 +2742,13 @@ TEST_F(P2PTransportChannelMultihomedTest, |
| // backup connection created using this new interface. |
| AddAddress(0, cellular[0], "test_cellular0", rtc::ADAPTER_TYPE_CELLULAR); |
| EXPECT_TRUE_WAIT( |
| - ep1_ch1()->GetState() == cricket::STATE_COMPLETED && |
| + ep1_ch1()->GetState() == STATE_COMPLETED && |
| (conn = GetConnectionWithLocalAddress(ep1_ch1(), cellular[0])) != |
| nullptr && |
| conn != ep1_ch1()->selected_connection() && conn->writable(), |
| kDefaultTimeout); |
| EXPECT_TRUE_WAIT( |
| - ep2_ch1()->GetState() == cricket::STATE_COMPLETED && |
| + ep2_ch1()->GetState() == STATE_COMPLETED && |
| (conn = GetConnectionWithRemoteAddress(ep2_ch1(), cellular[0])) != |
| nullptr && |
| conn != ep2_ch1()->selected_connection() && conn->receiving(), |
| @@ -2780,7 +2885,7 @@ TEST_F(P2PTransportChannelMultihomedTest, TestRestoreBackupConnection) { |
| EXPECT_TRUE_SIMULATED_WAIT( |
| GetConnectionWithLocalAddress(ep1_ch1(), cellular[0]) == nullptr, |
| kDefaultTimeout, clock); |
| - const cricket::Connection* conn; |
| + const Connection* conn; |
| EXPECT_TRUE_SIMULATED_WAIT( |
| (conn = GetConnectionWithLocalAddress(ep1_ch1(), cellular[0])) != |
| nullptr && |
| @@ -3038,9 +3143,11 @@ TEST_F(P2PTransportChannelPingTest, TestStunPingIntervals) { |
| SIMULATED_WAIT(conn->num_pings_sent() == ping_sent_before + 1, kMediumTimeout, |
| clock); |
| ping_interval_ms = (clock.TimeNanos() - start) / rtc::kNumNanosecsPerMillisec; |
| - EXPECT_GE(ping_interval_ms, STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL); |
| - EXPECT_LE(ping_interval_ms, |
| - STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL + SCHEDULING_RANGE); |
| + EXPECT_GE(ping_interval_ms, |
| + WEAK_OR_STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL); |
| + EXPECT_LE( |
| + ping_interval_ms, |
| + WEAK_OR_STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL + SCHEDULING_RANGE); |
| // Stabilized. |
| @@ -3054,9 +3161,11 @@ TEST_F(P2PTransportChannelPingTest, TestStunPingIntervals) { |
| SIMULATED_WAIT(conn->num_pings_sent() == ping_sent_before + 1, kMediumTimeout, |
| clock); |
| ping_interval_ms = (clock.TimeNanos() - start) / rtc::kNumNanosecsPerMillisec; |
| - EXPECT_GE(ping_interval_ms, STABLE_WRITABLE_CONNECTION_PING_INTERVAL); |
| - EXPECT_LE(ping_interval_ms, |
| - STABLE_WRITABLE_CONNECTION_PING_INTERVAL + SCHEDULING_RANGE); |
| + EXPECT_GE(ping_interval_ms, |
| + STRONG_AND_STABLE_WRITABLE_CONNECTION_PING_INTERVAL); |
| + EXPECT_LE( |
| + ping_interval_ms, |
| + STRONG_AND_STABLE_WRITABLE_CONNECTION_PING_INTERVAL + SCHEDULING_RANGE); |
| // Destabilized. |
| @@ -3077,15 +3186,17 @@ TEST_F(P2PTransportChannelPingTest, TestStunPingIntervals) { |
| SIMULATED_WAIT(conn->num_pings_sent() == ping_sent_before + 1, kMediumTimeout, |
| clock); |
| // The interval is expected to be |
| - // STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL. |
| + // WEAK_OR_STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL. |
| start = clock.TimeNanos(); |
| ping_sent_before = conn->num_pings_sent(); |
| SIMULATED_WAIT(conn->num_pings_sent() == ping_sent_before + 1, kMediumTimeout, |
| clock); |
| ping_interval_ms = (clock.TimeNanos() - start) / rtc::kNumNanosecsPerMillisec; |
| - EXPECT_GE(ping_interval_ms, STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL); |
| - EXPECT_LE(ping_interval_ms, |
| - STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL + SCHEDULING_RANGE); |
| + EXPECT_GE(ping_interval_ms, |
| + WEAK_OR_STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL); |
| + EXPECT_LE( |
| + ping_interval_ms, |
| + WEAK_OR_STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL + SCHEDULING_RANGE); |
| } |
| // Test that we start pinging as soon as we have a connection and remote ICE |