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