| Index: webrtc/p2p/base/p2ptransportchannel_unittest.cc | 
| diff --git a/webrtc/p2p/base/p2ptransportchannel_unittest.cc b/webrtc/p2p/base/p2ptransportchannel_unittest.cc | 
| index d7ee87300d9ed5f9d886bb7a0c8190d2a2e9c080..b7b5f530ee6c7c6101e8d3712b59a318fc684f8e 100644 | 
| --- a/webrtc/p2p/base/p2ptransportchannel_unittest.cc | 
| +++ b/webrtc/p2p/base/p2ptransportchannel_unittest.cc | 
| @@ -11,6 +11,7 @@ | 
| #include <algorithm> | 
| #include <memory> | 
|  | 
| +#include "webrtc/api/fakemetricsobserver.h" | 
| #include "webrtc/p2p/base/fakeportallocator.h" | 
| #include "webrtc/p2p/base/p2ptransportchannel.h" | 
| #include "webrtc/p2p/base/testrelayserver.h" | 
| @@ -198,9 +199,15 @@ class P2PTransportChannelTestBase : public testing::Test, | 
| ep1_.allocator_.reset( | 
| CreateBasicPortAllocator(&ep1_.network_manager_, stun_servers, | 
| kTurnUdpIntAddr, rtc::SocketAddress())); | 
| +    ep1_.metrics_observer_ = | 
| +        new rtc::RefCountedObject<webrtc::FakeMetricsObserver>(); | 
| +    ep1_.allocator_->set_metrics_observer(ep1_.metrics_observer_); | 
| ep2_.allocator_.reset( | 
| CreateBasicPortAllocator(&ep2_.network_manager_, stun_servers, | 
| kTurnUdpIntAddr, rtc::SocketAddress())); | 
| +    ep2_.metrics_observer_ = | 
| +        new rtc::RefCountedObject<webrtc::FakeMetricsObserver>(); | 
| +    ep2_.allocator_->set_metrics_observer(ep2_.metrics_observer_); | 
| } | 
|  | 
| protected: | 
| @@ -298,6 +305,9 @@ class P2PTransportChannelTestBase : public testing::Test, | 
| } | 
|  | 
| rtc::FakeNetworkManager network_manager_; | 
| +    // |metrics_observer_| should outlive |allocator_| as the former may be | 
| +    // used by the latter. | 
| +    rtc::scoped_refptr<webrtc::FakeMetricsObserver> metrics_observer_; | 
| std::unique_ptr<BasicPortAllocator> allocator_; | 
| ChannelData cd1_; | 
| ChannelData cd2_; | 
| @@ -416,6 +426,9 @@ class P2PTransportChannelTestBase : public testing::Test, | 
| PortAllocator* GetAllocator(int endpoint) { | 
| return GetEndpoint(endpoint)->allocator_.get(); | 
| } | 
| +  webrtc::FakeMetricsObserver* GetMetricsObserver(int endpoint) { | 
| +    return GetEndpoint(endpoint)->metrics_observer_; | 
| +  } | 
| void AddAddress(int endpoint, const SocketAddress& addr) { | 
| GetEndpoint(endpoint)->network_manager_.AddInterface(addr); | 
| } | 
| @@ -1172,6 +1185,187 @@ TEST_F(P2PTransportChannelTest, GetStats) { | 
| DestroyChannels(); | 
| } | 
|  | 
| +TEST_F(P2PTransportChannelTest, | 
| +       TestIceRegatheringReasonIceRestartWhenDisconnected) { | 
| +  rtc::ScopedFakeClock clock; | 
| +  ConfigureEndpoints(OPEN, OPEN, kOnlyLocalPorts, kOnlyLocalPorts); | 
| + | 
| +  CreateChannels(); | 
| +  EXPECT_TRUE_SIMULATED_WAIT(ep1_ch1()->receiving() && ep1_ch1()->writable() && | 
| +                                 ep2_ch1()->receiving() && | 
| +                                 ep2_ch1()->writable(), | 
| +                             kDefaultTimeout, clock); | 
| + | 
| +  // Drop all packets so that both channels become not writable. | 
| +  fw()->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, kPublicAddrs[0]); | 
| +  const int kWriteTimeoutDelay = 6000; | 
| +  EXPECT_TRUE_SIMULATED_WAIT(!ep1_ch1()->writable() && !ep2_ch1()->writable(), | 
| +                             kWriteTimeoutDelay, clock); | 
| + | 
| +  ep1_ch1()->SetIceParameters(kIceParams[2]); | 
| +  ep1_ch1()->SetRemoteIceParameters(kIceParams[3]); | 
| +  ep1_ch1()->MaybeStartGathering(); | 
| +  EXPECT_EQ(1, GetMetricsObserver(0)->GetEnumCounter( | 
| +                   webrtc::kEnumCounterIceRegatheringReason, | 
| +                   static_cast<int>( | 
| +                       IceRegatheringReason::ICE_RESTART_WHEN_DISCONNECTED))); | 
| + | 
| +  ep2_ch1()->SetIceParameters(kIceParams[3]); | 
| +  ep2_ch1()->SetRemoteIceParameters(kIceParams[2]); | 
| +  ep2_ch1()->MaybeStartGathering(); | 
| +  EXPECT_EQ(1, GetMetricsObserver(1)->GetEnumCounter( | 
| +                   webrtc::kEnumCounterIceRegatheringReason, | 
| +                   static_cast<int>( | 
| +                       IceRegatheringReason::ICE_RESTART_WHEN_DISCONNECTED))); | 
| + | 
| +  DestroyChannels(); | 
| +} | 
| + | 
| +TEST_F(P2PTransportChannelTest, | 
| +       TestIceRegatheringReasonIceRestartWhenConnected) { | 
| +  rtc::ScopedFakeClock clock; | 
| +  ConfigureEndpoints(OPEN, OPEN, kOnlyLocalPorts, kOnlyLocalPorts); | 
| + | 
| +  CreateChannels(); | 
| +  EXPECT_TRUE_SIMULATED_WAIT(ep1_ch1()->receiving() && ep1_ch1()->writable() && | 
| +                                 ep2_ch1()->receiving() && | 
| +                                 ep2_ch1()->writable(), | 
| +                             kDefaultTimeout, clock); | 
| + | 
| +  ep1_ch1()->SetIceParameters(kIceParams[2]); | 
| +  ep1_ch1()->SetRemoteIceParameters(kIceParams[3]); | 
| +  ep1_ch1()->MaybeStartGathering(); | 
| +  EXPECT_EQ( | 
| +      1, | 
| +      GetMetricsObserver(0)->GetEnumCounter( | 
| +          webrtc::kEnumCounterIceRegatheringReason, | 
| +          static_cast<int>(IceRegatheringReason::ICE_RESTART_WHEN_CONNECTED))); | 
| + | 
| +  ep2_ch1()->SetIceParameters(kIceParams[3]); | 
| +  ep2_ch1()->SetRemoteIceParameters(kIceParams[2]); | 
| +  ep2_ch1()->MaybeStartGathering(); | 
| +  EXPECT_EQ( | 
| +      1, | 
| +      GetMetricsObserver(1)->GetEnumCounter( | 
| +          webrtc::kEnumCounterIceRegatheringReason, | 
| +          static_cast<int>(IceRegatheringReason::ICE_RESTART_WHEN_CONNECTED))); | 
| + | 
| +  DestroyChannels(); | 
| +} | 
| + | 
| +TEST_F(P2PTransportChannelTest, | 
| +       TestIceRegatheringReasonIceRestartWhenConnecting) { | 
| +  rtc::ScopedFakeClock clock; | 
| +  ConfigureEndpoints(OPEN, OPEN, kOnlyLocalPorts, kOnlyLocalPorts); | 
| + | 
| +  // Create the channels without waiting for them to become connected. | 
| +  CreateChannels(); | 
| + | 
| +  ep1_ch1()->SetIceParameters(kIceParams[2]); | 
| +  ep1_ch1()->SetRemoteIceParameters(kIceParams[3]); | 
| +  ep1_ch1()->MaybeStartGathering(); | 
| +  EXPECT_EQ( | 
| +      1, | 
| +      GetMetricsObserver(0)->GetEnumCounter( | 
| +          webrtc::kEnumCounterIceRegatheringReason, | 
| +          static_cast<int>(IceRegatheringReason::ICE_RESTART_WHEN_CONNECTING))); | 
| + | 
| +  ep2_ch1()->SetIceParameters(kIceParams[3]); | 
| +  ep2_ch1()->SetRemoteIceParameters(kIceParams[2]); | 
| +  ep2_ch1()->MaybeStartGathering(); | 
| +  EXPECT_EQ( | 
| +      1, | 
| +      GetMetricsObserver(1)->GetEnumCounter( | 
| +          webrtc::kEnumCounterIceRegatheringReason, | 
| +          static_cast<int>(IceRegatheringReason::ICE_RESTART_WHEN_CONNECTING))); | 
| + | 
| +  DestroyChannels(); | 
| +} | 
| + | 
| +// Test the ICE regathering reason where there is a network change on | 
| +// both endpoints and one of them enables continual gathering but the other | 
| +// does not. | 
| +TEST_F(P2PTransportChannelTest, | 
| +       TestIceRegatheringReasonContinualGatheringByNetworkChange) { | 
| +  rtc::ScopedFakeClock clock; | 
| +  ConfigureEndpoints(OPEN, OPEN, kOnlyLocalPorts, kOnlyLocalPorts); | 
| + | 
| +  // ep1 gathers continually but ep2 does not. | 
| +  IceConfig continual_gathering_config = | 
| +      CreateIceConfig(1000, GATHER_CONTINUALLY); | 
| +  IceConfig default_config; | 
| +  CreateChannels(continual_gathering_config, default_config); | 
| + | 
| +  EXPECT_TRUE_SIMULATED_WAIT(ep1_ch1()->receiving() && ep1_ch1()->writable() && | 
| +                                 ep2_ch1()->receiving() && | 
| +                                 ep2_ch1()->writable(), | 
| +                             kDefaultTimeout, clock); | 
| + | 
| +  // Add address in ep1 will trigger continual gathering. | 
| +  AddAddress(0, kAlternateAddrs[0]); | 
| +  EXPECT_EQ_SIMULATED_WAIT( | 
| +      1, GetMetricsObserver(0)->GetEnumCounter( | 
| +             webrtc::kEnumCounterIceRegatheringReason, | 
| +             static_cast<int>( | 
| +                 IceRegatheringReason::CONTINUAL_GATHERING_BY_NETWORK_CHANGE)), | 
| +      kDefaultTimeout, clock); | 
| + | 
| +  ep2_ch1()->SetIceParameters(kIceParams[3]); | 
| +  ep2_ch1()->SetRemoteIceParameters(kIceParams[2]); | 
| +  ep2_ch1()->MaybeStartGathering(); | 
| + | 
| +  AddAddress(1, kAlternateAddrs[1]); | 
| +  SIMULATED_WAIT(false, kDefaultTimeout, clock); | 
| +  // ep2 has not enabled continual gathering. | 
| +  EXPECT_EQ( | 
| +      0, GetMetricsObserver(1)->GetEnumCounter( | 
| +             webrtc::kEnumCounterIceRegatheringReason, | 
| +             static_cast<int>( | 
| +                 IceRegatheringReason::CONTINUAL_GATHERING_BY_NETWORK_CHANGE))); | 
| + | 
| +  DestroyChannels(); | 
| +} | 
| + | 
| +// Test the ICE regathering reason where there is a network failure on | 
| +// both endpoints and one of them enables continual gathering but the other | 
| +// does not. | 
| +TEST_F(P2PTransportChannelTest, | 
| +       TestIceRegatheringReasonContinualGatheringByNetworkFailure) { | 
| +  rtc::ScopedFakeClock clock; | 
| +  ConfigureEndpoints(OPEN, OPEN, kOnlyLocalPorts, kOnlyLocalPorts); | 
| + | 
| +  // ep1 gathers continually but ep2 does not. | 
| +  IceConfig config1 = CreateIceConfig(1000, GATHER_CONTINUALLY); | 
| +  config1.regather_on_failed_networks_interval = rtc::Optional<int>(2000); | 
| +  IceConfig config2; | 
| +  config2.regather_on_failed_networks_interval = rtc::Optional<int>(2000); | 
| +  CreateChannels(config1, config2); | 
| + | 
| +  EXPECT_TRUE_SIMULATED_WAIT(ep1_ch1()->receiving() && ep1_ch1()->writable() && | 
| +                                 ep2_ch1()->receiving() && | 
| +                                 ep2_ch1()->writable(), | 
| +                             kDefaultTimeout, clock); | 
| + | 
| +  fw()->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, kPublicAddrs[0]); | 
| +  // Timeout value such that all connections are deleted. | 
| +  const int kNetworkFailureTimeout = 35000; | 
| +  SIMULATED_WAIT(false, kNetworkFailureTimeout, clock); | 
| +  EXPECT_LE( | 
| +      1, | 
| +      GetMetricsObserver(0)->GetEnumCounter( | 
| +          webrtc::kEnumCounterIceRegatheringReason, | 
| +          static_cast<int>( | 
| +              IceRegatheringReason::CONTINUAL_GATHERING_BY_NETWORK_FAILURE))); | 
| +  EXPECT_EQ( | 
| +      0, | 
| +      GetMetricsObserver(1)->GetEnumCounter( | 
| +          webrtc::kEnumCounterIceRegatheringReason, | 
| +          static_cast<int>( | 
| +              IceRegatheringReason::CONTINUAL_GATHERING_BY_NETWORK_FAILURE))); | 
| + | 
| +  DestroyChannels(); | 
| +} | 
| + | 
| // Test that we properly create a connection on a STUN ping from unknown address | 
| // when the signaling is slow. | 
| TEST_F(P2PTransportChannelTest, PeerReflexiveCandidateBeforeSignaling) { | 
|  |