summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortbansal <tbansal@chromium.org>2015-09-16 14:26:02 -0700
committerCommit bot <commit-bot@chromium.org>2015-09-16 21:26:53 +0000
commitb112feef767d087d6c40deb88c983d61c085d457 (patch)
tree19a4d5e0af0097f538636d6ef63efd87745c645c
parent8125ce3c695e6d8c02f3b51b16d49e17e7934bb4 (diff)
downloadchromium_src-b112feef767d087d6c40deb88c983d61c085d457.zip
chromium_src-b112feef767d087d6c40deb88c983d61c085d457.tar.gz
chromium_src-b112feef767d087d6c40deb88c983d61c085d457.tar.bz2
Populate EEP estimate in NQE
Call EEP on every network change, and populate the estimates into the NQE observation buffer. BUG=472685 Committed: https://crrev.com/9ee5d296239e3bc21b5c70259242ce6c4cefc96b Cr-Commit-Position: refs/heads/master@{#349032} Review URL: https://codereview.chromium.org/1316863006 Cr-Commit-Position: refs/heads/master@{#349232}
-rw-r--r--chrome/browser/android/net/external_estimate_provider_android.cc34
-rw-r--r--chrome/browser/android/net/external_estimate_provider_android.h21
-rw-r--r--chrome/browser/android/net/external_estimate_provider_android_unittest.cc39
-rw-r--r--net/base/external_estimate_provider.h4
-rw-r--r--net/base/network_quality_estimator.cc71
-rw-r--r--net/base/network_quality_estimator.h35
-rw-r--r--net/base/network_quality_estimator_unittest.cc382
-rw-r--r--tools/metrics/histograms/histograms.xml20
8 files changed, 517 insertions, 89 deletions
diff --git a/chrome/browser/android/net/external_estimate_provider_android.cc b/chrome/browser/android/net/external_estimate_provider_android.cc
index 2d8c2db..4a02f3b 100644
--- a/chrome/browser/android/net/external_estimate_provider_android.cc
+++ b/chrome/browser/android/net/external_estimate_provider_android.cc
@@ -33,13 +33,6 @@ ExternalEstimateProviderAndroid::~ExternalEstimateProviderAndroid() {
net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
}
-void ExternalEstimateProviderAndroid::RequestUpdate() const {
- DCHECK(thread_checker_.CalledOnValidThread());
- JNIEnv* env = base::android::AttachCurrentThread();
- Java_ExternalEstimateProviderAndroid_requestUpdate(
- env, j_external_estimate_provider_.obj());
-}
-
bool ExternalEstimateProviderAndroid::GetRTT(base::TimeDelta* rtt) const {
DCHECK(thread_checker_.CalledOnValidThread());
JNIEnv* env = base::android::AttachCurrentThread();
@@ -96,6 +89,23 @@ bool ExternalEstimateProviderAndroid::GetTimeSinceLastUpdate(
return true;
}
+void ExternalEstimateProviderAndroid::SetUpdatedEstimateDelegate(
+ net::ExternalEstimateProvider::UpdatedEstimateDelegate* delegate) {
+ delegate_ = delegate;
+}
+
+void ExternalEstimateProviderAndroid::Update() const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_ExternalEstimateProviderAndroid_requestUpdate(
+ env, j_external_estimate_provider_.obj());
+}
+
+void ExternalEstimateProviderAndroid::OnConnectionTypeChanged(
+ net::NetworkChangeNotifier::ConnectionType type) {
+ Update();
+}
+
void ExternalEstimateProviderAndroid::
NotifyExternalEstimateProviderAndroidUpdate(JNIEnv* env, jobject obj) {
if (!task_runner_)
@@ -113,19 +123,9 @@ void ExternalEstimateProviderAndroid::NotifyUpdatedEstimateAvailable() const {
delegate_->OnUpdatedEstimateAvailable();
}
-void ExternalEstimateProviderAndroid::OnConnectionTypeChanged(
- net::NetworkChangeNotifier::ConnectionType type) {
- RequestUpdate();
-}
-
bool RegisterExternalEstimateProviderAndroid(JNIEnv* env) {
return RegisterNativesImpl(env);
}
-void ExternalEstimateProviderAndroid::SetUpdatedEstimateDelegate(
- net::ExternalEstimateProvider::UpdatedEstimateDelegate* delegate) {
- delegate_ = delegate;
-}
-
} // namespace android
} // namespace chrome
diff --git a/chrome/browser/android/net/external_estimate_provider_android.h b/chrome/browser/android/net/external_estimate_provider_android.h
index ad787e1..8fe6729 100644
--- a/chrome/browser/android/net/external_estimate_provider_android.h
+++ b/chrome/browser/android/net/external_estimate_provider_android.h
@@ -34,30 +34,23 @@ class ExternalEstimateProviderAndroid
~ExternalEstimateProviderAndroid() override;
- // net::ExternalEstimateProvider implementation.
+ // net::ExternalEstimateProvider implementation:
bool GetRTT(base::TimeDelta* rtt) const override;
-
- // net::ExternalEstimateProvider implementation.
bool GetDownstreamThroughputKbps(
int32_t* downstream_throughput_kbps) const override;
-
- // net::ExternalEstimateProvider implementation.
bool GetUpstreamThroughputKbps(
int32_t* upstream_throughput_kbps) const override;
-
- // net::ExternalEstimateProvider implementation.
bool GetTimeSinceLastUpdate(
base::TimeDelta* time_since_last_update) const override;
+ void SetUpdatedEstimateDelegate(
+ net::ExternalEstimateProvider::UpdatedEstimateDelegate* delegate)
+ override;
+ void Update() const override;
// NetworkChangeNotifier::ConnectionTypeObserver implementation.
void OnConnectionTypeChanged(
net::NetworkChangeNotifier::ConnectionType type) override;
- // net::ExternalEstimateProvider implementation.
- void SetUpdatedEstimateDelegate(
- net::ExternalEstimateProvider::UpdatedEstimateDelegate* delegate)
- override;
-
// Called by Java when the external estimate provider has an updated value.
// This may be called on a thread different from |task_runner_|.
void NotifyExternalEstimateProviderAndroidUpdate(JNIEnv* env, jobject obj);
@@ -68,10 +61,6 @@ class ExternalEstimateProviderAndroid
void NotifyUpdatedEstimateAvailable() const;
private:
- // Places a requests to the provider to update the network quality. Returns
- // true if the request was placed successfully.
- void RequestUpdate() const;
-
// Value returned if valid value is unavailable.
int32_t no_value_ = -1;
diff --git a/chrome/browser/android/net/external_estimate_provider_android_unittest.cc b/chrome/browser/android/net/external_estimate_provider_android_unittest.cc
index 26d9d10..1c80b09 100644
--- a/chrome/browser/android/net/external_estimate_provider_android_unittest.cc
+++ b/chrome/browser/android/net/external_estimate_provider_android_unittest.cc
@@ -6,6 +6,7 @@
#include <stdint.h>
+#include "base/test/histogram_tester.h"
#include "base/time/time.h"
#include "net/base/network_quality_estimator.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -41,7 +42,10 @@ class TestNetworkQualityEstimator : public net::NetworkQualityEstimator {
~TestNetworkQualityEstimator() override {}
- void OnUpdatedEstimateAvailable() override { notified_ = true; }
+ void OnUpdatedEstimateAvailable() override {
+ notified_ = true;
+ net::NetworkQualityEstimator::OnUpdatedEstimateAvailable();
+ }
bool IsNotified() const { return notified_; }
@@ -56,11 +60,18 @@ class TestExternalEstimateProviderAndroid
: chrome::android::ExternalEstimateProviderAndroid() {}
~TestExternalEstimateProviderAndroid() override {}
using ExternalEstimateProviderAndroid::NotifyUpdatedEstimateAvailable;
+
+ bool GetTimeSinceLastUpdate(
+ base::TimeDelta* time_since_last_update) const override {
+ *time_since_last_update = base::TimeDelta::FromMilliseconds(1);
+ return true;
+ }
};
// Tests if the |ExternalEstimateProviderAndroid| notifies
// |NetworkQualityEstimator|.
TEST(ExternalEstimateProviderAndroidTest, DelegateTest) {
+ base::HistogramTester histogram_tester;
scoped_ptr<TestExternalEstimateProviderAndroid> external_estimate_provider;
external_estimate_provider.reset(new TestExternalEstimateProviderAndroid());
@@ -70,6 +81,32 @@ TEST(ExternalEstimateProviderAndroidTest, DelegateTest) {
external_estimate_provider.Pass(), variation_params);
ptr->NotifyUpdatedEstimateAvailable();
DCHECK(network_quality_estimator.IsNotified());
+
+ // EXTERNAL_ESTIMATE_PROVIDER_STATUS_NOT_AVAILABLE
+ histogram_tester.ExpectBucketCount("NQE.ExternalEstimateProviderStatus", 0,
+ 0);
+
+ // EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE
+ histogram_tester.ExpectBucketCount("NQE.ExternalEstimateProviderStatus", 1,
+ 1);
+
+ // EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERIED
+ // Updated once during NetworkQualityEstimator constructor and again,
+ // when |OnUpdatedEstimateAvailable| is called.
+ histogram_tester.ExpectBucketCount("NQE.ExternalEstimateProviderStatus", 2,
+ 2);
+
+ // EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERY_SUCCESSFUL
+ // Updated once during NetworkQualityEstimator constructor and again,
+ // when |OnUpdatedEstimateAvailable| is called.
+ histogram_tester.ExpectBucketCount("NQE.ExternalEstimateProviderStatus", 3,
+ 2);
+
+ // EXTERNAL_ESTIMATE_PROVIDER_STATUS_CALLBACK
+ histogram_tester.ExpectBucketCount("NQE.ExternalEstimateProviderStatus", 4,
+ 1);
+
+ histogram_tester.ExpectTotalCount("NQE.ExternalEstimateProviderStatus", 6);
}
} // namespace
diff --git a/net/base/external_estimate_provider.h b/net/base/external_estimate_provider.h
index bc02988..c4480cf 100644
--- a/net/base/external_estimate_provider.h
+++ b/net/base/external_estimate_provider.h
@@ -59,6 +59,10 @@ class NET_EXPORT ExternalEstimateProvider {
virtual void SetUpdatedEstimateDelegate(
UpdatedEstimateDelegate* delegate) = 0;
+ // Requests an updated network quality estimate from the external estimate
+ // provider.
+ virtual void Update() const = 0;
+
private:
DISALLOW_COPY_AND_ASSIGN(ExternalEstimateProvider);
};
diff --git a/net/base/network_quality_estimator.cc b/net/base/network_quality_estimator.cc
index 708a13c..d192bf0 100644
--- a/net/base/network_quality_estimator.cc
+++ b/net/base/network_quality_estimator.cc
@@ -178,7 +178,7 @@ NetworkQualityEstimator::NetworkQualityEstimator(
downstream_throughput_kbps_observations_(
GetWeightMultiplierPerSecond(variation_params)),
rtt_msec_observations_(GetWeightMultiplierPerSecond(variation_params)),
- external_estimates_provider_(external_estimates_provider.Pass()) {
+ external_estimate_provider_(external_estimates_provider.Pass()) {
static_assert(kMinRequestDurationMicroseconds > 0,
"Minimum request duration must be > 0");
static_assert(kDefaultHalfLifeSeconds > 0,
@@ -192,8 +192,15 @@ NetworkQualityEstimator::NetworkQualityEstimator(
ObtainOperatingParams(variation_params);
NetworkChangeNotifier::AddConnectionTypeObserver(this);
- if (external_estimates_provider_)
- external_estimates_provider_->SetUpdatedEstimateDelegate(this);
+ if (external_estimate_provider_) {
+ RecordExternalEstimateProviderMetrics(
+ EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE);
+ external_estimate_provider_->SetUpdatedEstimateDelegate(this);
+ QueryExternalEstimateProvider();
+ } else {
+ RecordExternalEstimateProviderMetrics(
+ EXTERNAL_ESTIMATE_PROVIDER_STATUS_NOT_AVAILABLE);
+ }
current_network_id_ = GetCurrentNetworkID();
AddDefaultEstimates();
}
@@ -210,6 +217,9 @@ void NetworkQualityEstimator::ObtainOperatingParams(
for (size_t i = 0; i <= NetworkChangeNotifier::CONNECTION_LAST; ++i) {
NetworkChangeNotifier::ConnectionType type =
static_cast<NetworkChangeNotifier::ConnectionType>(i);
+ DCHECK_EQ(InvalidRTT(), default_observations_[i].rtt());
+ DCHECK_EQ(kInvalidThroughput,
+ default_observations_[i].downstream_throughput_kbps());
int32_t variations_value = kMinimumRTTVariationParameterMsec - 1;
// Name of the parameter that holds the RTT value for this connection type.
std::string rtt_parameter_name =
@@ -419,6 +429,12 @@ bool NetworkQualityEstimator::RequestProvidesUsefulObservations(
request.creation_time() >= last_connection_change_;
}
+void NetworkQualityEstimator::RecordExternalEstimateProviderMetrics(
+ NQEExternalEstimateProviderStatus status) const {
+ UMA_HISTOGRAM_ENUMERATION("NQE.ExternalEstimateProviderStatus", status,
+ EXTERNAL_ESTIMATE_PROVIDER_STATUS_BOUNDARY);
+}
+
void NetworkQualityEstimator::OnConnectionTypeChanged(
NetworkChangeNotifier::ConnectionType type) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -538,6 +554,8 @@ void NetworkQualityEstimator::OnConnectionTypeChanged(
rtt_msec_observations_.Clear();
current_network_id_ = GetCurrentNetworkID();
+ QueryExternalEstimateProvider();
+
// Read any cached estimates for the new network. If cached estimates are
// unavailable, add the default estimates.
if (!ReadCachedNetworkQualityEstimate())
@@ -812,8 +830,51 @@ bool NetworkQualityEstimator::ReadCachedNetworkQualityEstimate() {
void NetworkQualityEstimator::OnUpdatedEstimateAvailable() {
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(external_estimates_provider_);
- // TODO(tbansal): Query provider for the recent value.
+ DCHECK(external_estimate_provider_);
+
+ RecordExternalEstimateProviderMetrics(
+ EXTERNAL_ESTIMATE_PROVIDER_STATUS_CALLBACK);
+ QueryExternalEstimateProvider();
+}
+
+void NetworkQualityEstimator::QueryExternalEstimateProvider() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (!external_estimate_provider_)
+ return;
+ RecordExternalEstimateProviderMetrics(
+ EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERIED);
+
+ base::TimeDelta time_since_last_update;
+
+ // Request a new estimate if estimate is not available, or if the available
+ // estimate is not fresh.
+ if (!external_estimate_provider_->GetTimeSinceLastUpdate(
+ &time_since_last_update) ||
+ time_since_last_update >
+ base::TimeDelta::FromMilliseconds(
+ kExternalEstimateProviderFreshnessDurationMsec)) {
+ // Request the external estimate provider for updated estimates. When the
+ // updates estimates are available, OnUpdatedEstimateAvailable() will be
+ // called.
+ external_estimate_provider_->Update();
+ return;
+ }
+
+ RecordExternalEstimateProviderMetrics(
+ EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERY_SUCCESSFUL);
+ base::TimeDelta rtt;
+ if (external_estimate_provider_->GetRTT(&rtt)) {
+ rtt_msec_observations_.AddObservation(
+ Observation(rtt.InMilliseconds(), base::TimeTicks::Now()));
+ }
+
+ int32_t downstream_throughput_kbps;
+ if (external_estimate_provider_->GetDownstreamThroughputKbps(
+ &downstream_throughput_kbps)) {
+ downstream_throughput_kbps_observations_.AddObservation(
+ Observation(downstream_throughput_kbps, base::TimeTicks::Now()));
+ }
}
void NetworkQualityEstimator::CacheNetworkQualityEstimate() {
diff --git a/net/base/network_quality_estimator.h b/net/base/network_quality_estimator.h
index aba0313..f951bd4 100644
--- a/net/base/network_quality_estimator.h
+++ b/net/base/network_quality_estimator.h
@@ -149,6 +149,9 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
void OnConnectionTypeChanged(
NetworkChangeNotifier::ConnectionType type) override;
+ // ExternalEstimateProvider::UpdatedEstimateObserver implementation.
+ void OnUpdatedEstimateAvailable() override;
+
private:
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, StoreObservations);
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestKbpsRTTUpdates);
@@ -165,6 +168,10 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
TestLRUCacheMaximumSize);
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestGetMedianRTTSince);
+ FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
+ TestExternalEstimateProvider);
+ FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
+ TestExternalEstimateProviderMergeEstimates);
// NetworkQuality is used to cache the quality of a network connection.
class NET_EXPORT_PRIVATE NetworkQuality {
@@ -352,12 +359,18 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// Maximum number of observations that can be held in the ObservationBuffer.
static const size_t kMaximumObservationsBufferSize = 300;
+ // Time duration (in milliseconds) after which the estimate provided by
+ // external estimate provider is considered stale.
+ static const int kExternalEstimateProviderFreshnessDurationMsec =
+ 5 * 60 * 1000;
+
// Returns the RTT value to be used when the valid RTT is unavailable. Readers
// should discard RTT if it is set to the value returned by |InvalidRTT()|.
static const base::TimeDelta InvalidRTT();
- // ExternalEstimateProvider::UpdatedEstimateObserver implementation:
- void OnUpdatedEstimateAvailable() override;
+ // Queries the external estimate provider for the latest network quality
+ // estimates, and adds those estimates to the current observation buffer.
+ void QueryExternalEstimateProvider();
// Obtains operating parameters from the field trial parameters.
void ObtainOperatingParams(
@@ -396,6 +409,22 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// observations.
bool RequestProvidesUsefulObservations(const URLRequest& request) const;
+ // Values of external estimate provider status. This enum must remain
+ // synchronized with the enum of the same name in
+ // metrics/histograms/histograms.xml.
+ enum NQEExternalEstimateProviderStatus {
+ EXTERNAL_ESTIMATE_PROVIDER_STATUS_NOT_AVAILABLE,
+ EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE,
+ EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERIED,
+ EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERY_SUCCESSFUL,
+ EXTERNAL_ESTIMATE_PROVIDER_STATUS_CALLBACK,
+ EXTERNAL_ESTIMATE_PROVIDER_STATUS_BOUNDARY
+ };
+
+ // Records the metrics related to external estimate provider.
+ void RecordExternalEstimateProviderMetrics(
+ NQEExternalEstimateProviderStatus status) const;
+
// Determines if the requests to local host can be used in estimating the
// network quality. Set to true only for tests.
const bool allow_localhost_requests_;
@@ -439,7 +468,7 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// ExternalEstimateProvider that provides network quality using operating
// system APIs. May be NULL.
- const scoped_ptr<ExternalEstimateProvider> external_estimates_provider_;
+ const scoped_ptr<ExternalEstimateProvider> external_estimate_provider_;
base::ThreadChecker thread_checker_;
diff --git a/net/base/network_quality_estimator_unittest.cc b/net/base/network_quality_estimator_unittest.cc
index b1ffdeb..38a22eb 100644
--- a/net/base/network_quality_estimator_unittest.cc
+++ b/net/base/network_quality_estimator_unittest.cc
@@ -10,6 +10,7 @@
#include <map>
#include "base/basictypes.h"
+#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram_samples.h"
@@ -21,22 +22,47 @@
#include "net/base/external_estimate_provider.h"
#include "net/base/load_flags.h"
#include "net/base/network_change_notifier.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/http/http_status_code.h"
+#include "net/test/spawned_test_server/spawned_test_server.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace {
+#if !defined(OS_IOS)
+// SpawnedTestServer is not supported on iOS.
+// Less verbose way of running a simple testserver for the tests below.
+class LocalHttpTestServer : public net::SpawnedTestServer {
+ public:
+ LocalHttpTestServer()
+ : net::SpawnedTestServer(net::SpawnedTestServer::TYPE_HTTP,
+ net::SpawnedTestServer::kLocalhost,
+ base::FilePath()) {}
+};
+#endif // !defined(OS_IOS)
+
// Helps in setting the current network type and id.
class TestNetworkQualityEstimator : public net::NetworkQualityEstimator {
public:
TestNetworkQualityEstimator(
- const std::map<std::string, std::string>& variation_params)
- : NetworkQualityEstimator(scoped_ptr<net::ExternalEstimateProvider>(),
+ const std::map<std::string, std::string>& variation_params,
+ scoped_ptr<net::ExternalEstimateProvider> external_estimate_provider)
+ : NetworkQualityEstimator(external_estimate_provider.Pass(),
variation_params,
true,
- true) {}
+ true) {
+#if !defined(OS_IOS)
+ // Set up test server.
+ DCHECK(test_server_.Start());
+#endif // !defined(OS_IOS)
+ }
+
+ explicit TestNetworkQualityEstimator(
+ const std::map<std::string, std::string>& variation_params)
+ : TestNetworkQualityEstimator(
+ variation_params,
+ scoped_ptr<net::ExternalEstimateProvider>()) {}
~TestNetworkQualityEstimator() override {}
@@ -49,6 +75,11 @@ class TestNetworkQualityEstimator : public net::NetworkQualityEstimator {
OnConnectionTypeChanged(type);
}
+#if !defined(OS_IOS)
+ // Returns a GURL hosted at embedded test server.
+ const GURL GetEchoURL() const { return test_server_.GetURL("/echo.html"); }
+#endif // !defined(OS_IOS)
+
using NetworkQualityEstimator::ReadCachedNetworkQualityEstimate;
using NetworkQualityEstimator::OnConnectionTypeChanged;
@@ -62,18 +93,22 @@ class TestNetworkQualityEstimator : public net::NetworkQualityEstimator {
net::NetworkChangeNotifier::ConnectionType current_network_type_;
std::string current_network_id_;
+
+#if !defined(OS_IOS)
+ // Test server used for testing.
+ LocalHttpTestServer test_server_;
+#endif // !defined(OS_IOS)
+
+ DISALLOW_COPY_AND_ASSIGN(TestNetworkQualityEstimator);
};
} // namespace
namespace net {
+#if !defined(OS_IOS)
+// SpawnedTestServer is not supported on iOS.
TEST(NetworkQualityEstimatorTest, TestKbpsRTTUpdates) {
- net::test_server::EmbeddedTestServer embedded_test_server;
- embedded_test_server.ServeFilesFromDirectory(
- base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest")));
- ASSERT_TRUE(embedded_test_server.InitializeAndWaitUntilReady());
-
base::HistogramTester histogram_tester;
// Enable requests to local host to be used for network quality estimation.
std::map<std::string, std::string> variation_params;
@@ -86,19 +121,17 @@ TEST(NetworkQualityEstimatorTest, TestKbpsRTTUpdates) {
base::TimeTicks(), 100));
TestDelegate test_delegate;
- TestURLRequestContext context(false);
+ TestURLRequestContext context(true);
+ context.set_network_quality_estimator(&estimator);
+ context.Init();
- scoped_ptr<URLRequest> request(
- context.CreateRequest(embedded_test_server.GetURL("/echo.html"),
- DEFAULT_PRIORITY, &test_delegate));
+ scoped_ptr<URLRequest> request(context.CreateRequest(
+ estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate));
request->SetLoadFlags(request->load_flags() | LOAD_MAIN_FRAME);
request->Start();
-
base::RunLoop().Run();
// Both RTT and downstream throughput should be updated.
- estimator.NotifyHeadersReceived(*request);
- estimator.NotifyRequestCompleted(*request);
EXPECT_NE(NetworkQualityEstimator::InvalidRTT(),
estimator.GetRTTEstimateInternal(base::TimeTicks(), 100));
EXPECT_NE(NetworkQualityEstimator::kInvalidThroughput,
@@ -123,8 +156,12 @@ TEST(NetworkQualityEstimatorTest, TestKbpsRTTUpdates) {
histogram_tester.ExpectTotalCount("NQE.RatioEstimatedToActualRTT.Unknown", 0);
- estimator.NotifyHeadersReceived(*request);
- estimator.NotifyRequestCompleted(*request);
+ scoped_ptr<URLRequest> request2(context.CreateRequest(
+ estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate));
+ request2->SetLoadFlags(request2->load_flags() | LOAD_MAIN_FRAME);
+ request2->Start();
+ base::RunLoop().Run();
+
histogram_tester.ExpectTotalCount("NQE.RTTObservations.Unknown", 1);
estimator.SimulateNetworkChangeTo(
NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1");
@@ -166,26 +203,20 @@ TEST(NetworkQualityEstimatorTest, TestKbpsRTTUpdates) {
}
TEST(NetworkQualityEstimatorTest, StoreObservations) {
- net::test_server::EmbeddedTestServer embedded_test_server;
- embedded_test_server.ServeFilesFromDirectory(
- base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest")));
- ASSERT_TRUE(embedded_test_server.InitializeAndWaitUntilReady());
-
std::map<std::string, std::string> variation_params;
TestNetworkQualityEstimator estimator(variation_params);
+
TestDelegate test_delegate;
- TestURLRequestContext context(false);
+ TestURLRequestContext context(true);
+ context.set_network_quality_estimator(&estimator);
+ context.Init();
// Push 10 more observations than the maximum buffer size.
for (size_t i = 0; i < estimator.kMaximumObservationsBufferSize + 10U; ++i) {
- scoped_ptr<URLRequest> request(
- context.CreateRequest(embedded_test_server.GetURL("/echo.html"),
- DEFAULT_PRIORITY, &test_delegate));
+ scoped_ptr<URLRequest> request(context.CreateRequest(
+ estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate));
request->Start();
base::RunLoop().Run();
-
- estimator.NotifyHeadersReceived(*request);
- estimator.NotifyRequestCompleted(*request);
}
EXPECT_EQ(static_cast<size_t>(
@@ -200,11 +231,8 @@ TEST(NetworkQualityEstimatorTest, StoreObservations) {
NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-2");
EXPECT_EQ(0U, estimator.downstream_throughput_kbps_observations_.Size());
EXPECT_EQ(0U, estimator.rtt_msec_observations_.Size());
-
- scoped_ptr<URLRequest> request(
- context.CreateRequest(embedded_test_server.GetURL("/echo.html"),
- DEFAULT_PRIORITY, &test_delegate));
}
+#endif // !defined(OS_IOS)
// Verifies that the percentiles are correctly computed. All observations have
// the same timestamp. Kbps percentiles must be in decreasing order. RTT
@@ -315,12 +343,9 @@ TEST(NetworkQualityEstimatorTest, PercentileDifferentTimestamps) {
// This test notifies NetworkQualityEstimator of received data. Next,
// throughput and RTT percentiles are checked for correctness by doing simple
// verifications.
+#if !defined(OS_IOS)
+// SpawnedTestServer is not supported on iOS.
TEST(NetworkQualityEstimatorTest, ComputedPercentiles) {
- net::test_server::EmbeddedTestServer embedded_test_server;
- embedded_test_server.ServeFilesFromDirectory(
- base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest")));
- ASSERT_TRUE(embedded_test_server.InitializeAndWaitUntilReady());
-
std::map<std::string, std::string> variation_params;
TestNetworkQualityEstimator estimator(variation_params);
@@ -331,19 +356,16 @@ TEST(NetworkQualityEstimatorTest, ComputedPercentiles) {
base::TimeTicks(), 100));
TestDelegate test_delegate;
- TestURLRequestContext context(false);
+ TestURLRequestContext context(true);
+ context.set_network_quality_estimator(&estimator);
+ context.Init();
// Number of observations are more than the maximum buffer size.
for (size_t i = 0; i < estimator.kMaximumObservationsBufferSize + 100U; ++i) {
- scoped_ptr<URLRequest> request(
- context.CreateRequest(embedded_test_server.GetURL("/echo.html"),
- DEFAULT_PRIORITY, &test_delegate));
+ scoped_ptr<URLRequest> request(context.CreateRequest(
+ estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate));
request->Start();
base::RunLoop().Run();
-
- // Use different number of bytes to create variation.
- estimator.NotifyHeadersReceived(*request);
- estimator.NotifyRequestCompleted(*request);
}
// Verify the percentiles through simple tests.
@@ -367,6 +389,7 @@ TEST(NetworkQualityEstimatorTest, ComputedPercentiles) {
}
}
}
+#endif // !defined(OS_IOS)
TEST(NetworkQualityEstimatorTest, ObtainOperatingParams) {
std::map<std::string, std::string> variation_params;
@@ -654,4 +677,269 @@ TEST(NetworkQualityEstimatorTest, TestGetMedianRTTSince) {
EXPECT_EQ(100, downstream_throughput_kbps);
}
+// An external estimate provider that does not have a valid RTT or throughput
+// estimate.
+class InvalidExternalEstimateProvider : public ExternalEstimateProvider {
+ public:
+ InvalidExternalEstimateProvider() : get_rtt_count_(0) {}
+ ~InvalidExternalEstimateProvider() override {}
+
+ // ExternalEstimateProvider implementation:
+ bool GetRTT(base::TimeDelta* rtt) const override {
+ DCHECK(rtt);
+ get_rtt_count_++;
+ return false;
+ }
+
+ // ExternalEstimateProvider implementation:
+ bool GetDownstreamThroughputKbps(
+ int32_t* downstream_throughput_kbps) const override {
+ DCHECK(downstream_throughput_kbps);
+ return false;
+ }
+
+ // ExternalEstimateProvider implementation:
+ bool GetUpstreamThroughputKbps(
+ int32_t* upstream_throughput_kbps) const override {
+ // NetworkQualityEstimator does not support upstream throughput.
+ ADD_FAILURE();
+ return false;
+ }
+
+ // ExternalEstimateProvider implementation:
+ bool GetTimeSinceLastUpdate(
+ base::TimeDelta* time_since_last_update) const override {
+ *time_since_last_update = base::TimeDelta::FromMilliseconds(1);
+ return true;
+ }
+
+ // ExternalEstimateProvider implementation:
+ void SetUpdatedEstimateDelegate(UpdatedEstimateDelegate* delegate) override {}
+
+ // ExternalEstimateProvider implementation:
+ void Update() const override {}
+
+ size_t get_rtt_count() const { return get_rtt_count_; }
+
+ private:
+ // Keeps track of number of times different functions were called.
+ mutable size_t get_rtt_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(InvalidExternalEstimateProvider);
+};
+
+// Tests if the RTT value from external estimate provider is discarded if the
+// external estimate provider is invalid.
+TEST(NetworkQualityEstimatorTest, InvalidExternalEstimateProvider) {
+ InvalidExternalEstimateProvider* invalid_external_estimate_provider =
+ new InvalidExternalEstimateProvider();
+ scoped_ptr<ExternalEstimateProvider> external_estimate_provider(
+ invalid_external_estimate_provider);
+
+ TestNetworkQualityEstimator estimator(std::map<std::string, std::string>(),
+ external_estimate_provider.Pass());
+
+ base::TimeDelta rtt;
+ int32_t kbps;
+ EXPECT_EQ(1U, invalid_external_estimate_provider->get_rtt_count());
+ EXPECT_FALSE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
+}
+
+class TestExternalEstimateProvider : public ExternalEstimateProvider {
+ public:
+ TestExternalEstimateProvider(base::TimeDelta rtt,
+ int32_t downstream_throughput_kbps)
+ : rtt_(rtt),
+ downstream_throughput_kbps_(downstream_throughput_kbps),
+ time_since_last_update_(base::TimeDelta::FromSeconds(1)),
+ get_time_since_last_update_count_(0),
+ get_rtt_count_(0),
+ get_downstream_throughput_kbps_count_(0),
+ update_count_(0) {}
+ ~TestExternalEstimateProvider() override {}
+
+ // ExternalEstimateProvider implementation:
+ bool GetRTT(base::TimeDelta* rtt) const override {
+ *rtt = rtt_;
+ get_rtt_count_++;
+ return true;
+ }
+
+ // ExternalEstimateProvider implementation:
+ bool GetDownstreamThroughputKbps(
+ int32_t* downstream_throughput_kbps) const override {
+ *downstream_throughput_kbps = downstream_throughput_kbps_;
+ get_downstream_throughput_kbps_count_++;
+ return true;
+ }
+
+ // ExternalEstimateProvider implementation:
+ bool GetUpstreamThroughputKbps(
+ int32_t* upstream_throughput_kbps) const override {
+ // NetworkQualityEstimator does not support upstream throughput.
+ ADD_FAILURE();
+ return false;
+ }
+
+ // ExternalEstimateProvider implementation:
+ bool GetTimeSinceLastUpdate(
+ base::TimeDelta* time_since_last_update) const override {
+ *time_since_last_update = time_since_last_update_;
+ get_time_since_last_update_count_++;
+ return true;
+ }
+
+ // ExternalEstimateProvider implementation:
+ void SetUpdatedEstimateDelegate(UpdatedEstimateDelegate* delegate) override {}
+
+ // ExternalEstimateProvider implementation:
+ void Update() const override { update_count_++; }
+
+ void set_time_since_last_update(base::TimeDelta time_since_last_update) {
+ time_since_last_update_ = time_since_last_update;
+ }
+
+ size_t get_time_since_last_update_count() const {
+ return get_time_since_last_update_count_;
+ }
+ size_t get_rtt_count() const { return get_rtt_count_; }
+ size_t get_downstream_throughput_kbps_count() const {
+ return get_downstream_throughput_kbps_count_;
+ }
+ size_t update_count() const { return update_count_; }
+
+ private:
+ // RTT and downstream throughput estimates.
+ const base::TimeDelta rtt_;
+ const int32_t downstream_throughput_kbps_;
+
+ base::TimeDelta time_since_last_update_;
+
+ // Keeps track of number of times different functions were called.
+ mutable size_t get_time_since_last_update_count_;
+ mutable size_t get_rtt_count_;
+ mutable size_t get_downstream_throughput_kbps_count_;
+ mutable size_t update_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestExternalEstimateProvider);
+};
+
+// Tests if the external estimate provider is called in the constructor and
+// on network change notification.
+TEST(NetworkQualityEstimatorTest, TestExternalEstimateProvider) {
+ TestExternalEstimateProvider* test_external_estimate_provider =
+ new TestExternalEstimateProvider(base::TimeDelta::FromMilliseconds(1),
+ 100);
+ scoped_ptr<ExternalEstimateProvider> external_estimate_provider(
+ test_external_estimate_provider);
+ std::map<std::string, std::string> variation_params;
+ TestNetworkQualityEstimator estimator(variation_params,
+ external_estimate_provider.Pass());
+
+ base::TimeDelta rtt;
+ int32_t kbps;
+ EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
+
+ EXPECT_EQ(
+ 1U, test_external_estimate_provider->get_time_since_last_update_count());
+ EXPECT_EQ(1U, test_external_estimate_provider->get_rtt_count());
+ EXPECT_EQ(
+ 1U,
+ test_external_estimate_provider->get_downstream_throughput_kbps_count());
+
+ // Change network type to WiFi. Number of queries to External estimate
+ // provider must increment.
+ estimator.SimulateNetworkChangeTo(
+ NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test-1");
+ EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
+ EXPECT_EQ(
+ 2U, test_external_estimate_provider->get_time_since_last_update_count());
+ EXPECT_EQ(2U, test_external_estimate_provider->get_rtt_count());
+ EXPECT_EQ(
+ 2U,
+ test_external_estimate_provider->get_downstream_throughput_kbps_count());
+
+ // Change network type to 2G. Number of queries to External estimate provider
+ // must increment.
+ estimator.SimulateNetworkChangeTo(
+ NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-1");
+ EXPECT_EQ(
+ 3U, test_external_estimate_provider->get_time_since_last_update_count());
+ EXPECT_EQ(3U, test_external_estimate_provider->get_rtt_count());
+ EXPECT_EQ(
+ 3U,
+ test_external_estimate_provider->get_downstream_throughput_kbps_count());
+
+ // Set the external estimate as old. Network Quality estimator should request
+ // an update on connection type change.
+ EXPECT_EQ(0U, test_external_estimate_provider->update_count());
+ test_external_estimate_provider->set_time_since_last_update(
+ base::TimeDelta::Max());
+
+ estimator.SimulateNetworkChangeTo(
+ NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test-2");
+ EXPECT_EQ(
+ 4U, test_external_estimate_provider->get_time_since_last_update_count());
+ EXPECT_EQ(3U, test_external_estimate_provider->get_rtt_count());
+ EXPECT_EQ(
+ 3U,
+ test_external_estimate_provider->get_downstream_throughput_kbps_count());
+ EXPECT_EQ(1U, test_external_estimate_provider->update_count());
+
+ // Estimates are unavailable because external estimate provider never
+ // notifies network quality estimator of the updated estimates.
+ EXPECT_FALSE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_FALSE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
+}
+
+// Tests if the estimate from the external estimate provider is merged with the
+// observations collected from the HTTP requests.
+#if !defined(OS_IOS)
+// SpawnedTestServer is not supported on iOS.
+TEST(NetworkQualityEstimatorTest, TestExternalEstimateProviderMergeEstimates) {
+ const base::TimeDelta external_estimate_provider_rtt =
+ base::TimeDelta::FromMilliseconds(1);
+ const int32_t external_estimate_provider_downstream_throughput = 100;
+ TestExternalEstimateProvider* test_external_estimate_provider =
+ new TestExternalEstimateProvider(
+ external_estimate_provider_rtt,
+ external_estimate_provider_downstream_throughput);
+ scoped_ptr<ExternalEstimateProvider> external_estimate_provider(
+ test_external_estimate_provider);
+
+ std::map<std::string, std::string> variation_params;
+ TestNetworkQualityEstimator estimator(variation_params,
+ external_estimate_provider.Pass());
+
+ base::TimeDelta rtt;
+ // Estimate provided by network quality estimator should match the estimate
+ // provided by external estimate provider.
+ EXPECT_TRUE(estimator.GetRTTEstimate(&rtt));
+ EXPECT_EQ(external_estimate_provider_rtt, rtt);
+
+ int32_t kbps;
+ EXPECT_TRUE(estimator.GetDownlinkThroughputKbpsEstimate(&kbps));
+ EXPECT_EQ(external_estimate_provider_downstream_throughput, kbps);
+
+ EXPECT_EQ(1U, estimator.rtt_msec_observations_.Size());
+ EXPECT_EQ(1U, estimator.downstream_throughput_kbps_observations_.Size());
+
+ TestDelegate test_delegate;
+ TestURLRequestContext context(true);
+ context.set_network_quality_estimator(&estimator);
+ context.Init();
+
+ scoped_ptr<URLRequest> request(context.CreateRequest(
+ estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate));
+ request->Start();
+ base::RunLoop().Run();
+
+ EXPECT_EQ(2U, estimator.rtt_msec_observations_.Size());
+ EXPECT_EQ(2U, estimator.downstream_throughput_kbps_observations_.Size());
+}
+#endif // !defined(OS_IOS)
+
} // namespace net
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 677ff2e..49e0cc6 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -28577,6 +28577,18 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
</summary>
</histogram>
+<histogram name="NQE.ExternalEstimateProviderStatus"
+ enum="NQEExternalEstimateProviderStatus">
+ <owner>bengr@chromium.org</owner>
+ <owner>tbansal@chromium.org</owner>
+ <summary>
+ Records the interaction (availability and query count) of Network Quality
+ Estimator with external estimates provider. Logged on network change events,
+ everytime external estimate provider is queried for an updated estimate, and
+ when it proactively notifies that an updated estimate is available.
+ </summary>
+</histogram>
+
<histogram name="NQE.FastestRTT" units="milliseconds">
<owner>bengr@chromium.org</owner>
<owner>tbansal@chromium.org</owner>
@@ -66899,6 +66911,14 @@ To add a new entry, add it with any value and run test to compute valid value.
<int value="2" label="Enabled">NPAPI is enabled</int>
</enum>
+<enum name="NQEExternalEstimateProviderStatus" type="int">
+ <int value="0" label="External estimate provider was not available"/>
+ <int value="1" label="External estimate provider was available"/>
+ <int value="2" label="External estimate provider was queried"/>
+ <int value="3" label="Query to external estimate provider was successful"/>
+ <int value="4" label="Callback received from external estimate provider"/>
+</enum>
+
<enum name="NtpFollowAction" type="int">
<int value="0" label="PAGE_TRANSITION_LINK"/>
<int value="1" label="PAGE_TRANSITION_TYPED"/>