1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "services/network/network_quality_estimator_manager.h"
6
7 #include <algorithm>
8 #include <utility>
9
10 #include "base/macros.h"
11 #include "base/run_loop.h"
12 #include "base/test/task_environment.h"
13 #include "base/time/time.h"
14 #include "mojo/public/cpp/bindings/receiver.h"
15 #include "net/log/test_net_log.h"
16 #include "net/nqe/effective_connection_type.h"
17 #include "net/nqe/network_quality_estimator.h"
18 #include "services/network/public/mojom/network_quality_estimator_manager.mojom.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace network {
22
23 namespace {
24
25 class TestNetworkQualityEstimatorManagerClient
26 : public mojom::NetworkQualityEstimatorManagerClient {
27 public:
TestNetworkQualityEstimatorManagerClient(NetworkQualityEstimatorManager * network_quality_estimator_manager)28 explicit TestNetworkQualityEstimatorManagerClient(
29 NetworkQualityEstimatorManager* network_quality_estimator_manager)
30 : network_quality_estimator_manager_(network_quality_estimator_manager),
31 num_network_quality_changed_(0),
32 run_loop_(std::make_unique<base::RunLoop>()),
33 effective_connection_type_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN),
34 http_rtt_(base::TimeDelta()),
35 transport_rtt_(base::TimeDelta()),
36 downlink_bandwidth_kbps_(INT32_MAX) {
37 mojo::Remote<mojom::NetworkQualityEstimatorManager> manager;
38 network_quality_estimator_manager_->AddReceiver(
39 manager.BindNewPipeAndPassReceiver());
40
41 manager->RequestNotifications(receiver_.BindNewPipeAndPassRemote());
42 }
43
~TestNetworkQualityEstimatorManagerClient()44 ~TestNetworkQualityEstimatorManagerClient() override {}
45
OnNetworkQualityChanged(net::EffectiveConnectionType type,base::TimeDelta http_rtt,base::TimeDelta transport_rtt,int32_t downlink_bandwidth_kbps)46 void OnNetworkQualityChanged(net::EffectiveConnectionType type,
47 base::TimeDelta http_rtt,
48 base::TimeDelta transport_rtt,
49 int32_t downlink_bandwidth_kbps) override {
50 num_network_quality_changed_++;
51 effective_connection_type_ = type;
52 http_rtt_ = http_rtt;
53 transport_rtt_ = transport_rtt;
54 downlink_bandwidth_kbps_ = downlink_bandwidth_kbps;
55 if (run_loop_wait_effective_connection_type_ == type)
56 run_loop_->Quit();
57 }
58
59 // Returns the number of OnNetworkQualityChanged() notifications. Note that
60 // the number may change based on the order in which underlying network
61 // quality estimator provides notifications when effective connection
62 // type, RTT and downlink estimates change simultaneously.
num_network_quality_changed() const63 size_t num_network_quality_changed() const {
64 return num_network_quality_changed_;
65 }
66
WaitForNotification(net::EffectiveConnectionType effective_connection_type)67 void WaitForNotification(
68 net::EffectiveConnectionType effective_connection_type) {
69 run_loop_wait_effective_connection_type_ = effective_connection_type;
70 run_loop_->Run();
71 run_loop_.reset(new base::RunLoop());
72 }
73
effective_connection_type() const74 net::EffectiveConnectionType effective_connection_type() const {
75 return effective_connection_type_;
76 }
http_rtt() const77 base::TimeDelta http_rtt() const { return http_rtt_; }
transport_rtt() const78 base::TimeDelta transport_rtt() const { return transport_rtt_; }
downlink_bandwidth_kbps() const79 int32_t downlink_bandwidth_kbps() const { return downlink_bandwidth_kbps_; }
80
81 private:
82 NetworkQualityEstimatorManager* network_quality_estimator_manager_;
83 size_t num_network_quality_changed_;
84 std::unique_ptr<base::RunLoop> run_loop_;
85 net::EffectiveConnectionType run_loop_wait_effective_connection_type_;
86 net::EffectiveConnectionType effective_connection_type_;
87 base::TimeDelta http_rtt_;
88 base::TimeDelta transport_rtt_;
89 int32_t downlink_bandwidth_kbps_;
90 mojo::Receiver<mojom::NetworkQualityEstimatorManagerClient> receiver_{this};
91
92 DISALLOW_COPY_AND_ASSIGN(TestNetworkQualityEstimatorManagerClient);
93 };
94
95 } // namespace
96
97 class NetworkQualityEstimatorManagerTest : public testing::Test {
98 public:
NetworkQualityEstimatorManagerTest()99 NetworkQualityEstimatorManagerTest()
100 : net_log_(std::make_unique<net::RecordingBoundTestNetLog>()),
101 network_quality_estimator_manager_(
102 std::make_unique<NetworkQualityEstimatorManager>(
103 net_log_->bound().net_log())) {
104 // Change the network quality to UNKNOWN to prevent any spurious
105 // notifications.
106 SimulateNetworkQualityChange(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
107 network_quality_estimator_manager_client_ =
108 std::make_unique<TestNetworkQualityEstimatorManagerClient>(
109 network_quality_estimator_manager_.get());
110 }
111
~NetworkQualityEstimatorManagerTest()112 ~NetworkQualityEstimatorManagerTest() override {}
113
114 TestNetworkQualityEstimatorManagerClient*
network_quality_estimator_manager_client()115 network_quality_estimator_manager_client() {
116 return network_quality_estimator_manager_client_.get();
117 }
118
network_quality_estimator_manager() const119 NetworkQualityEstimatorManager* network_quality_estimator_manager() const {
120 return network_quality_estimator_manager_.get();
121 }
122
SimulateNetworkQualityChange(net::EffectiveConnectionType type)123 void SimulateNetworkQualityChange(net::EffectiveConnectionType type) {
124 network_quality_estimator_manager_->GetNetworkQualityEstimator()
125 ->SimulateNetworkQualityChangeForTesting(type);
126 }
127
128 private:
129 base::test::TaskEnvironment task_environment_;
130 std::unique_ptr<net::RecordingBoundTestNetLog> net_log_;
131 std::unique_ptr<NetworkQualityEstimatorManager>
132 network_quality_estimator_manager_;
133 std::unique_ptr<TestNetworkQualityEstimatorManagerClient>
134 network_quality_estimator_manager_client_;
135
136 DISALLOW_COPY_AND_ASSIGN(NetworkQualityEstimatorManagerTest);
137 };
138
TEST_F(NetworkQualityEstimatorManagerTest,ClientNotified)139 TEST_F(NetworkQualityEstimatorManagerTest, ClientNotified) {
140 // Simulate a new network quality change.
141 SimulateNetworkQualityChange(net::EFFECTIVE_CONNECTION_TYPE_3G);
142 network_quality_estimator_manager_client()->WaitForNotification(
143 net::EFFECTIVE_CONNECTION_TYPE_3G);
144 EXPECT_EQ(
145 net::EFFECTIVE_CONNECTION_TYPE_3G,
146 network_quality_estimator_manager_client()->effective_connection_type());
147 base::RunLoop().RunUntilIdle();
148 // Verify that not more than 2 notifications were received.
149 EXPECT_GE(2u, network_quality_estimator_manager_client()
150 ->num_network_quality_changed());
151 // Typical RTT and downlink values when effective connection type is 3G. Taken
152 // from net::NetworkQualityEstimatorParams.
153 EXPECT_EQ(base::TimeDelta::FromMilliseconds(450),
154 network_quality_estimator_manager_client()->http_rtt());
155 EXPECT_EQ(base::TimeDelta::FromMilliseconds(400),
156 network_quality_estimator_manager_client()->transport_rtt());
157 EXPECT_EQ(
158 400,
159 network_quality_estimator_manager_client()->downlink_bandwidth_kbps());
160 }
161
162 // Test that when the network quality is unavailable, network quality estimator
163 // manager reports the estimated network quality values as negative.
TEST_F(NetworkQualityEstimatorManagerTest,ClientNotifiedUnknownNetworkQuality)164 TEST_F(NetworkQualityEstimatorManagerTest,
165 ClientNotifiedUnknownNetworkQuality) {
166 EXPECT_EQ(
167 net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN,
168 network_quality_estimator_manager_client()->effective_connection_type());
169 base::RunLoop().RunUntilIdle();
170
171 SimulateNetworkQualityChange(net::EFFECTIVE_CONNECTION_TYPE_3G);
172 network_quality_estimator_manager_client()->WaitForNotification(
173 net::EFFECTIVE_CONNECTION_TYPE_3G);
174 base::RunLoop().RunUntilIdle();
175 // Typical RTT and downlink values when effective connection type is 3G. Taken
176 // from net::NetworkQualityEstimatorParams.
177 EXPECT_EQ(base::TimeDelta::FromMilliseconds(450),
178 network_quality_estimator_manager_client()->http_rtt());
179 EXPECT_EQ(base::TimeDelta::FromMilliseconds(400),
180 network_quality_estimator_manager_client()->transport_rtt());
181 EXPECT_EQ(
182 400,
183 network_quality_estimator_manager_client()->downlink_bandwidth_kbps());
184
185 SimulateNetworkQualityChange(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
186 network_quality_estimator_manager_client()->WaitForNotification(
187 net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
188 base::RunLoop().RunUntilIdle();
189 EXPECT_GT(base::TimeDelta(),
190 network_quality_estimator_manager_client()->http_rtt());
191 EXPECT_GT(base::TimeDelta(),
192 network_quality_estimator_manager_client()->transport_rtt());
193 EXPECT_GT(
194 0, network_quality_estimator_manager_client()->downlink_bandwidth_kbps());
195 }
196
TEST_F(NetworkQualityEstimatorManagerTest,OneClientPipeBroken)197 TEST_F(NetworkQualityEstimatorManagerTest, OneClientPipeBroken) {
198 auto network_quality_estimator_manager_client2 =
199 std::make_unique<TestNetworkQualityEstimatorManagerClient>(
200 network_quality_estimator_manager());
201
202 // Simulate a network quality change.
203 SimulateNetworkQualityChange(net::EFFECTIVE_CONNECTION_TYPE_4G);
204
205 network_quality_estimator_manager_client()->WaitForNotification(
206 net::EFFECTIVE_CONNECTION_TYPE_4G);
207 network_quality_estimator_manager_client2->WaitForNotification(
208 net::EFFECTIVE_CONNECTION_TYPE_4G);
209 EXPECT_EQ(
210 net::EFFECTIVE_CONNECTION_TYPE_4G,
211 network_quality_estimator_manager_client()->effective_connection_type());
212 EXPECT_EQ(
213 net::EFFECTIVE_CONNECTION_TYPE_4G,
214 network_quality_estimator_manager_client2->effective_connection_type());
215 // Typical RTT and downlink values when effective connection type is 4G. Taken
216 // from net::NetworkQualityEstimatorParams.
217 EXPECT_EQ(base::TimeDelta::FromMilliseconds(175),
218 network_quality_estimator_manager_client2->http_rtt());
219 EXPECT_EQ(base::TimeDelta::FromMilliseconds(125),
220 network_quality_estimator_manager_client()->transport_rtt());
221 EXPECT_EQ(
222 1600,
223 network_quality_estimator_manager_client2->downlink_bandwidth_kbps());
224 base::RunLoop().RunUntilIdle();
225
226 EXPECT_GE(2u, network_quality_estimator_manager_client()
227 ->num_network_quality_changed());
228 EXPECT_GE(
229 2u,
230 network_quality_estimator_manager_client2->num_network_quality_changed());
231 network_quality_estimator_manager_client2.reset();
232
233 base::RunLoop().RunUntilIdle();
234
235 // Simulate a second network quality change, and the remaining client should
236 // be notified.
237 SimulateNetworkQualityChange(net::EFFECTIVE_CONNECTION_TYPE_2G);
238
239 network_quality_estimator_manager_client()->WaitForNotification(
240 net::EFFECTIVE_CONNECTION_TYPE_2G);
241 EXPECT_EQ(
242 net::EFFECTIVE_CONNECTION_TYPE_2G,
243 network_quality_estimator_manager_client()->effective_connection_type());
244 EXPECT_GE(3u, network_quality_estimator_manager_client()
245 ->num_network_quality_changed());
246 EXPECT_EQ(base::TimeDelta::FromMilliseconds(1800),
247 network_quality_estimator_manager_client()->http_rtt());
248 EXPECT_EQ(base::TimeDelta::FromMilliseconds(1500),
249 network_quality_estimator_manager_client()->transport_rtt());
250 EXPECT_EQ(
251 75,
252 network_quality_estimator_manager_client()->downlink_bandwidth_kbps());
253 }
254
TEST_F(NetworkQualityEstimatorManagerTest,NewClientReceivesCurrentEffectiveType)255 TEST_F(NetworkQualityEstimatorManagerTest,
256 NewClientReceivesCurrentEffectiveType) {
257 // Simulate a network quality change.
258 SimulateNetworkQualityChange(net::EFFECTIVE_CONNECTION_TYPE_2G);
259
260 network_quality_estimator_manager_client()->WaitForNotification(
261 net::EFFECTIVE_CONNECTION_TYPE_2G);
262 EXPECT_EQ(
263 net::EFFECTIVE_CONNECTION_TYPE_2G,
264 network_quality_estimator_manager_client()->effective_connection_type());
265 base::RunLoop().RunUntilIdle();
266 // Typical RTT and downlink values when effective connection type is 2G. Taken
267 // from net::NetworkQualityEstimatorParams.
268 EXPECT_EQ(base::TimeDelta::FromMilliseconds(1800),
269 network_quality_estimator_manager_client()->http_rtt());
270 EXPECT_EQ(base::TimeDelta::FromMilliseconds(1500),
271 network_quality_estimator_manager_client()->transport_rtt());
272 EXPECT_EQ(
273 75,
274 network_quality_estimator_manager_client()->downlink_bandwidth_kbps());
275
276 // Register a new client after the network quality change and it should
277 // receive the up-to-date effective connection type.
278 TestNetworkQualityEstimatorManagerClient
279 network_quality_estimator_manager_client2(
280 network_quality_estimator_manager());
281 network_quality_estimator_manager_client2.WaitForNotification(
282 net::EFFECTIVE_CONNECTION_TYPE_2G);
283 EXPECT_EQ(
284 net::EFFECTIVE_CONNECTION_TYPE_2G,
285 network_quality_estimator_manager_client2.effective_connection_type());
286 // Typical RTT and downlink values when when effective connection type is 2G.
287 // Taken from net::NetworkQualityEstimatorParams.
288 EXPECT_EQ(base::TimeDelta::FromMilliseconds(1800),
289 network_quality_estimator_manager_client2.http_rtt());
290 EXPECT_EQ(base::TimeDelta::FromMilliseconds(1500),
291 network_quality_estimator_manager_client()->transport_rtt());
292 EXPECT_EQ(
293 75, network_quality_estimator_manager_client2.downlink_bandwidth_kbps());
294 }
295
296 } // namespace network
297