Index: net/base/network_quality_estimator_unittest.cc |
diff --git a/net/base/network_quality_estimator_unittest.cc b/net/base/network_quality_estimator_unittest.cc |
index 25e386db44db573184f628053115c75be6ea87e5..c7648ba9c2c4ba4cb18b707dc2052dfae2bcc4ad 100644 |
--- a/net/base/network_quality_estimator_unittest.cc |
+++ b/net/base/network_quality_estimator_unittest.cc |
@@ -4,9 +4,12 @@ |
#include "net/base/network_quality_estimator.h" |
+#include <stddef.h> |
#include <stdint.h> |
+ |
#include <limits> |
#include <map> |
+#include <string> |
#include <utility> |
#include <vector> |
@@ -23,6 +26,7 @@ |
#include "net/base/external_estimate_provider.h" |
#include "net/base/load_flags.h" |
#include "net/base/network_change_notifier.h" |
+#include "net/base/socket_performance_watcher_factory.h" |
#include "net/http/http_status_code.h" |
#include "net/test/embedded_test_server/embedded_test_server.h" |
#include "net/test/embedded_test_server/http_request.h" |
@@ -157,6 +161,45 @@ class TestThroughputObserver |
std::vector<Observation> observations_; |
}; |
+class TestPacketLossObserver |
+ : public net::NetworkQualityEstimator::PacketLossObserver { |
+ public: |
+ struct Observation { |
+ Observation(size_t packets_missing, |
+ size_t packets_received_in_order, |
+ size_t packets_received_out_of_order, |
+ const base::TimeTicks& ts, |
+ net::NetworkQualityEstimator::ObservationSource src) |
+ : packets_missing(packets_missing), |
+ packets_received_in_order(packets_received_in_order), |
+ packets_received_out_of_order(packets_received_out_of_order), |
+ timestamp(ts), |
+ source(src) {} |
+ size_t packets_missing; |
+ size_t packets_received_in_order; |
+ size_t packets_received_out_of_order; |
+ base::TimeTicks timestamp; |
+ net::NetworkQualityEstimator::ObservationSource source; |
+ }; |
+ |
+ std::vector<Observation>& observations() { return observations_; } |
+ |
+ // PacketLossObserver implementation: |
+ void OnPacketLossObservation( |
+ size_t packets_missing, |
+ size_t packets_received_in_order, |
+ size_t packets_received_out_of_order, |
+ const base::TimeTicks& timestamp, |
+ net::NetworkQualityEstimator::ObservationSource source) override { |
+ observations_.push_back( |
+ Observation(packets_missing, packets_received_in_order, |
+ packets_received_out_of_order, timestamp, source)); |
+ } |
+ |
+ private: |
+ std::vector<Observation> observations_; |
+}; |
+ |
} // namespace |
namespace net { |
@@ -255,6 +298,110 @@ TEST(NetworkQualityEstimatorTest, TestKbpsRTTUpdates) { |
EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
} |
+// Tests that packet loss rate is updated correctly. |
+TEST(NetworkQualityEstimatorTest, TestPacketLossRateUpdates) { |
+ std::map<std::string, std::string> variation_params; |
+ TestNetworkQualityEstimator estimator(variation_params); |
+ |
+ float packet_loss_rate; |
+ EXPECT_FALSE(estimator.GetPacketLossRateEstimate(&packet_loss_rate)); |
+ |
+ estimator.OnUpdatedPacketCountAvailable( |
+ NetworkQualityEstimator::PROTOCOL_QUIC, 0, 1, 1); |
+ |
+ EXPECT_TRUE(estimator.GetPacketLossRateEstimate(&packet_loss_rate)); |
+ EXPECT_NEAR(0.0f, packet_loss_rate, 0.001f); |
+ |
+ estimator.SimulateNetworkChangeTo( |
+ NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, std::string()); |
+ |
+ EXPECT_FALSE(estimator.GetPacketLossRateEstimate(&packet_loss_rate)); |
+ |
+ // Expecting packet number i, but received packet numbers from i+9 to i+11. |
+ estimator.OnUpdatedPacketCountAvailable( |
+ NetworkQualityEstimator::PROTOCOL_QUIC, 9, 3, 0); |
+ EXPECT_TRUE(estimator.GetPacketLossRateEstimate(&packet_loss_rate)); |
+ EXPECT_NEAR(9.0f / 12, packet_loss_rate, 0.001f); |
+ |
+ // Expecting packet number i+12, and received packet number i+12. |
+ estimator.OnUpdatedPacketCountAvailable( |
+ NetworkQualityEstimator::PROTOCOL_QUIC, 0, 1, 0); |
+ EXPECT_TRUE(estimator.GetPacketLossRateEstimate(&packet_loss_rate)); |
+ EXPECT_NEAR(9.0f / 13, packet_loss_rate, 0.001f); |
+ |
+ // Expecting packet number i+13, and received packet number i+3. |
+ estimator.OnUpdatedPacketCountAvailable( |
+ NetworkQualityEstimator::PROTOCOL_QUIC, 0, 0, 1); |
+ EXPECT_TRUE(estimator.GetPacketLossRateEstimate(&packet_loss_rate)); |
+ EXPECT_NEAR(9.0f / 13, packet_loss_rate, 0.001f); |
+ |
+ // Expecting packet number i+13, and received packet number i+15. |
+ estimator.OnUpdatedPacketCountAvailable( |
+ NetworkQualityEstimator::PROTOCOL_QUIC, 0, 1, 0); |
+ EXPECT_TRUE(estimator.GetPacketLossRateEstimate(&packet_loss_rate)); |
+ EXPECT_NEAR(9.0f / 14, packet_loss_rate, 0.001f); |
+} |
+ |
+// Tests that packet loss UMA histogram is recorded properly. |
+TEST(NetworkQualityEstimatorTest, TestPacketLossRateHistogram) { |
+ std::map<std::string, std::string> variation_params; |
+ TestNetworkQualityEstimator estimator(variation_params); |
+ |
+ TestDelegate test_delegate; |
+ TestURLRequestContext context(true); |
+ context.set_network_quality_estimator(&estimator); |
+ context.Init(); |
+ |
+ const struct { |
+ bool notify_packet_counts; |
+ bool set_mainframe_flag; |
+ } tests[] = { |
+ { |
+ false, false, |
+ }, |
+ { |
+ false, true, |
+ }, |
+ { |
+ true, false, |
+ }, |
+ { |
+ true, true, |
+ }, |
+ }; |
+ |
+ for (const auto& test : tests) { |
+ base::HistogramTester histogram_tester; |
+ estimator.SimulateNetworkChangeTo( |
+ NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test"); |
+ |
+ float packet_loss_rate; |
+ EXPECT_FALSE(estimator.GetPacketLossRateEstimate(&packet_loss_rate)); |
+ |
+ if (test.notify_packet_counts) { |
+ estimator.OnUpdatedPacketCountAvailable( |
+ NetworkQualityEstimator::PROTOCOL_QUIC, 0, 1, 1); |
+ } |
+ EXPECT_EQ(test.notify_packet_counts, |
+ estimator.GetPacketLossRateEstimate(&packet_loss_rate)); |
+ |
+ for (size_t i = 0; i < 2; ++i) { |
+ // Check UMA histograms. |
+ scoped_ptr<URLRequest> request(context.CreateRequest( |
+ estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); |
+ if (test.set_mainframe_flag) { |
+ request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME); |
+ } |
+ request->Start(); |
+ base::RunLoop().Run(); |
+ size_t expect_histogram_count = |
+ test.notify_packet_counts && test.set_mainframe_flag ? i + 1 : 0; |
+ histogram_tester.ExpectTotalCount("NQE.PacketLossRate.WiFi", |
+ expect_histogram_count); |
+ } |
+ } |
+} |
+ |
TEST(NetworkQualityEstimatorTest, StoreObservations) { |
std::map<std::string, std::string> variation_params; |
TestNetworkQualityEstimator estimator(variation_params); |
@@ -299,6 +446,8 @@ TEST(NetworkQualityEstimatorTest, PercentileSameTimestamps) { |
EXPECT_FALSE(estimator.GetRTTEstimate(&rtt)); |
int32_t kbps; |
EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
+ float packet_loss_rate; |
+ EXPECT_FALSE(estimator.GetPacketLossRateEstimate(&packet_loss_rate)); |
// Insert samples from {1,2,3,..., 100}. First insert odd samples, then even |
// samples. This helps in verifying that the order of samples does not matter. |
@@ -310,8 +459,12 @@ TEST(NetworkQualityEstimatorTest, PercentileSameTimestamps) { |
NetworkQualityEstimator::RttObservation( |
base::TimeDelta::FromMilliseconds(i), now, |
NetworkQualityEstimator::URL_REQUEST)); |
+ estimator.packet_loss_rate_observations_.AddObservation( |
+ NetworkQualityEstimator::PacketLossRateObservation( |
+ 0.0f, now, NetworkQualityEstimator::QUIC)); |
EXPECT_TRUE(estimator.GetRTTEstimate(&rtt)); |
EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
+ EXPECT_TRUE(estimator.GetPacketLossRateEstimate(&packet_loss_rate)); |
} |
for (int i = 2; i <= 100; i += 2) { |
@@ -322,8 +475,12 @@ TEST(NetworkQualityEstimatorTest, PercentileSameTimestamps) { |
NetworkQualityEstimator::RttObservation( |
base::TimeDelta::FromMilliseconds(i), now, |
NetworkQualityEstimator::URL_REQUEST)); |
+ estimator.packet_loss_rate_observations_.AddObservation( |
+ NetworkQualityEstimator::PacketLossRateObservation( |
+ 1.0, now, NetworkQualityEstimator::QUIC)); |
EXPECT_TRUE(estimator.GetRTTEstimate(&rtt)); |
EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps)); |
+ EXPECT_TRUE(estimator.GetPacketLossRateEstimate(&packet_loss_rate)); |
} |
for (int i = 0; i <= 100; ++i) { |
@@ -346,6 +503,8 @@ TEST(NetworkQualityEstimatorTest, PercentileSameTimestamps) { |
base::TimeTicks(), 50) > 0); |
EXPECT_TRUE(estimator.GetRTTEstimateInternal(base::TimeTicks(), 50) != |
NetworkQualityEstimator::InvalidRTT()); |
+ EXPECT_TRUE(estimator.GetPacketLossRateEstimate(&packet_loss_rate)); |
+ EXPECT_NEAR(0.5f, packet_loss_rate, 0.001f); |
} |
// Verifies that the percentiles are correctly computed. Observations have |
@@ -359,6 +518,9 @@ TEST(NetworkQualityEstimatorTest, PercentileDifferentTimestamps) { |
base::TimeTicks now = base::TimeTicks::Now(); |
base::TimeTicks very_old = base::TimeTicks::UnixEpoch(); |
+ float packet_loss_rate; |
+ EXPECT_FALSE(estimator.GetPacketLossRateEstimate(&packet_loss_rate)); |
+ |
// First 50 samples have very old timestamp. |
for (int i = 1; i <= 50; ++i) { |
estimator.downstream_throughput_kbps_observations_.AddObservation( |
@@ -368,6 +530,9 @@ TEST(NetworkQualityEstimatorTest, PercentileDifferentTimestamps) { |
NetworkQualityEstimator::RttObservation( |
base::TimeDelta::FromMilliseconds(i), very_old, |
NetworkQualityEstimator::URL_REQUEST)); |
+ estimator.packet_loss_rate_observations_.AddObservation( |
+ NetworkQualityEstimator::PacketLossRateObservation( |
+ 0.0f, very_old, NetworkQualityEstimator::QUIC)); |
} |
// Next 50 (i.e., from 51 to 100) have recent timestamp. |
@@ -379,6 +544,9 @@ TEST(NetworkQualityEstimatorTest, PercentileDifferentTimestamps) { |
NetworkQualityEstimator::RttObservation( |
base::TimeDelta::FromMilliseconds(i), now, |
NetworkQualityEstimator::URL_REQUEST)); |
+ estimator.packet_loss_rate_observations_.AddObservation( |
+ NetworkQualityEstimator::PacketLossRateObservation( |
+ 1.0, now, NetworkQualityEstimator::QUIC)); |
} |
// Older samples have very little weight. So, all percentiles are >= 51 |
@@ -402,6 +570,9 @@ TEST(NetworkQualityEstimatorTest, PercentileDifferentTimestamps) { |
EXPECT_EQ(NetworkQualityEstimator::kInvalidThroughput, |
estimator.GetDownlinkThroughputKbpsEstimateInternal( |
base::TimeTicks::Now() + base::TimeDelta::FromMinutes(10), 50)); |
+ |
+ EXPECT_TRUE(estimator.GetPacketLossRateEstimate(&packet_loss_rate)); |
+ EXPECT_NEAR(1.0, packet_loss_rate, 0.001f); |
} |
// This test notifies NetworkQualityEstimator of received data. Next, |
@@ -536,9 +707,9 @@ TEST(NetworkQualityEstimatorTest, HalfLifeParam) { |
// Half life parameter is not set. Default value of |
// |weight_multiplier_per_second_| should be used. |
TestNetworkQualityEstimator estimator(variation_params); |
- EXPECT_NEAR(0.988, estimator.downstream_throughput_kbps_observations_ |
- .weight_multiplier_per_second_, |
- 0.001); |
+ EXPECT_NEAR(0.988f, estimator.downstream_throughput_kbps_observations_ |
+ .weight_multiplier_per_second_, |
+ 0.001f); |
} |
variation_params["HalfLifeSeconds"] = "-100"; |
@@ -546,9 +717,9 @@ TEST(NetworkQualityEstimatorTest, HalfLifeParam) { |
// Half life parameter is set to a negative value. Default value of |
// |weight_multiplier_per_second_| should be used. |
TestNetworkQualityEstimator estimator(variation_params); |
- EXPECT_NEAR(0.988, estimator.downstream_throughput_kbps_observations_ |
- .weight_multiplier_per_second_, |
- 0.001); |
+ EXPECT_NEAR(0.988f, estimator.downstream_throughput_kbps_observations_ |
+ .weight_multiplier_per_second_, |
+ 0.001f); |
} |
variation_params["HalfLifeSeconds"] = "0"; |
@@ -556,18 +727,18 @@ TEST(NetworkQualityEstimatorTest, HalfLifeParam) { |
// Half life parameter is set to zero. Default value of |
// |weight_multiplier_per_second_| should be used. |
TestNetworkQualityEstimator estimator(variation_params); |
- EXPECT_NEAR(0.988, estimator.downstream_throughput_kbps_observations_ |
- .weight_multiplier_per_second_, |
- 0.001); |
+ EXPECT_NEAR(0.988f, estimator.downstream_throughput_kbps_observations_ |
+ .weight_multiplier_per_second_, |
+ 0.001f); |
} |
variation_params["HalfLifeSeconds"] = "10"; |
{ |
// Half life parameter is set to a valid value. |
TestNetworkQualityEstimator estimator(variation_params); |
- EXPECT_NEAR(0.933, estimator.downstream_throughput_kbps_observations_ |
- .weight_multiplier_per_second_, |
- 0.001); |
+ EXPECT_NEAR(0.933f, estimator.downstream_throughput_kbps_observations_ |
+ .weight_multiplier_per_second_, |
+ 0.001f); |
} |
} |
@@ -1026,10 +1197,12 @@ TEST(NetworkQualityEstimatorTest, TestExternalEstimateProviderMergeEstimates) { |
TEST(NetworkQualityEstimatorTest, TestObservers) { |
TestRTTObserver rtt_observer; |
TestThroughputObserver throughput_observer; |
+ TestPacketLossObserver packet_loss_observer; |
std::map<std::string, std::string> variation_params; |
TestNetworkQualityEstimator estimator(variation_params); |
estimator.AddRTTObserver(&rtt_observer); |
estimator.AddThroughputObserver(&throughput_observer); |
+ estimator.AddPacketLossObserver(&packet_loss_observer); |
TestDelegate test_delegate; |
TestURLRequestContext context(true); |
@@ -1052,6 +1225,14 @@ TEST(NetworkQualityEstimatorTest, TestObservers) { |
request2->Start(); |
base::RunLoop().Run(); |
+ float packet_loss_rate; |
+ EXPECT_FALSE(estimator.GetPacketLossRateEstimate(&packet_loss_rate)); |
+ |
+ estimator.OnUpdatedPacketCountAvailable( |
+ NetworkQualityEstimator::PROTOCOL_QUIC, 0, 1, 1); |
+ EXPECT_TRUE(estimator.GetPacketLossRateEstimate(&packet_loss_rate)); |
+ EXPECT_NEAR(0.0f, packet_loss_rate, 0.001f); |
+ |
// Both RTT and downstream throughput should be updated. |
EXPECT_NE(NetworkQualityEstimator::InvalidRTT(), |
estimator.GetRTTEstimateInternal(base::TimeTicks(), 100)); |
@@ -1061,16 +1242,24 @@ TEST(NetworkQualityEstimatorTest, TestObservers) { |
EXPECT_EQ(2U, rtt_observer.observations().size()); |
EXPECT_EQ(2U, throughput_observer.observations().size()); |
- for (auto observation : rtt_observer.observations()) { |
+ ASSERT_EQ(1U, packet_loss_observer.observations().size()); |
+ for (const auto& observation : rtt_observer.observations()) { |
EXPECT_LE(0, observation.rtt_ms); |
EXPECT_LE(0, (observation.timestamp - then).InMilliseconds()); |
EXPECT_EQ(NetworkQualityEstimator::URL_REQUEST, observation.source); |
} |
- for (auto observation : throughput_observer.observations()) { |
+ for (const auto& observation : throughput_observer.observations()) { |
EXPECT_LE(0, observation.throughput_kbps); |
EXPECT_LE(0, (observation.timestamp - then).InMilliseconds()); |
EXPECT_EQ(NetworkQualityEstimator::URL_REQUEST, observation.source); |
} |
+ for (const auto& observation : packet_loss_observer.observations()) { |
+ EXPECT_LE(0u, observation.packets_missing); |
+ EXPECT_LE(1u, observation.packets_received_in_order); |
+ EXPECT_LE(0u, observation.packets_received_out_of_order); |
+ EXPECT_LE(0, (observation.timestamp - then).InMilliseconds()); |
+ EXPECT_EQ(NetworkQualityEstimator::QUIC, observation.source); |
+ } |
// Verify that observations from TCP and QUIC are passed on to the observers. |
base::TimeDelta tcp_rtt(base::TimeDelta::FromMilliseconds(1)); |