• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Chromium Authors
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 "net/base/network_change_notifier.h"
6 
7 #include "base/run_loop.h"
8 #include "build/build_config.h"
9 #include "net/base/mock_network_change_notifier.h"
10 #include "net/base/network_interfaces.h"
11 #include "net/test/test_connection_cost_observer.h"
12 #include "net/test/test_with_task_environment.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 
15 namespace net {
16 
17 // Note: This test is subject to the host's OS and network connection. This test
18 // is not future-proof. New standards will come about necessitating the need to
19 // alter the ranges of these tests.
TEST(NetworkChangeNotifierTest,NetMaxBandwidthRange)20 TEST(NetworkChangeNotifierTest, NetMaxBandwidthRange) {
21   NetworkChangeNotifier::ConnectionType connection_type =
22       NetworkChangeNotifier::CONNECTION_NONE;
23   double max_bandwidth = 0.0;
24   NetworkChangeNotifier::GetMaxBandwidthAndConnectionType(&max_bandwidth,
25                                                           &connection_type);
26 
27   // Always accept infinity as it's the default value if the bandwidth is
28   // unknown.
29   if (max_bandwidth == std::numeric_limits<double>::infinity()) {
30     EXPECT_NE(NetworkChangeNotifier::CONNECTION_NONE, connection_type);
31     return;
32   }
33 
34   switch (connection_type) {
35     case NetworkChangeNotifier::CONNECTION_UNKNOWN:
36       EXPECT_EQ(std::numeric_limits<double>::infinity(), max_bandwidth);
37       break;
38     case NetworkChangeNotifier::CONNECTION_ETHERNET:
39       EXPECT_GE(10.0, max_bandwidth);
40       EXPECT_LE(10000.0, max_bandwidth);
41       break;
42     case NetworkChangeNotifier::CONNECTION_WIFI:
43       EXPECT_GE(1.0, max_bandwidth);
44       EXPECT_LE(7000.0, max_bandwidth);
45       break;
46     case NetworkChangeNotifier::CONNECTION_2G:
47       EXPECT_GE(0.01, max_bandwidth);
48       EXPECT_LE(0.384, max_bandwidth);
49       break;
50     case NetworkChangeNotifier::CONNECTION_3G:
51       EXPECT_GE(2.0, max_bandwidth);
52       EXPECT_LE(42.0, max_bandwidth);
53       break;
54     case NetworkChangeNotifier::CONNECTION_4G:
55       EXPECT_GE(100.0, max_bandwidth);
56       EXPECT_LE(100.0, max_bandwidth);
57       break;
58     case NetworkChangeNotifier::CONNECTION_5G:
59       // TODO(crbug.com/40148439): Expect proper bounds once we have introduced
60       // subtypes for 5G connections.
61       EXPECT_EQ(std::numeric_limits<double>::infinity(), max_bandwidth);
62       break;
63     case NetworkChangeNotifier::CONNECTION_NONE:
64       EXPECT_EQ(0.0, max_bandwidth);
65       break;
66     case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
67       EXPECT_GE(1.0, max_bandwidth);
68       EXPECT_LE(24.0, max_bandwidth);
69       break;
70   }
71 }
72 
TEST(NetworkChangeNotifierTest,ConnectionTypeFromInterfaceList)73 TEST(NetworkChangeNotifierTest, ConnectionTypeFromInterfaceList) {
74   NetworkInterfaceList list;
75 
76   // Test empty list.
77   EXPECT_EQ(NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list),
78             NetworkChangeNotifier::CONNECTION_NONE);
79 
80   for (int i = NetworkChangeNotifier::CONNECTION_UNKNOWN;
81        i <= NetworkChangeNotifier::CONNECTION_LAST; i++) {
82     // Check individual types.
83     NetworkInterface interface;
84     interface.type = static_cast<NetworkChangeNotifier::ConnectionType>(i);
85     list.clear();
86     list.push_back(interface);
87     EXPECT_EQ(NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list), i);
88     // Check two types.
89     for (int j = NetworkChangeNotifier::CONNECTION_UNKNOWN;
90          j <= NetworkChangeNotifier::CONNECTION_LAST; j++) {
91       list.clear();
92       interface.type = static_cast<NetworkChangeNotifier::ConnectionType>(i);
93       list.push_back(interface);
94       interface.type = static_cast<NetworkChangeNotifier::ConnectionType>(j);
95       list.push_back(interface);
96       EXPECT_EQ(NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list),
97                 i == j ? i : NetworkChangeNotifier::CONNECTION_UNKNOWN);
98     }
99   }
100 }
101 
TEST(NetworkChangeNotifierTest,IgnoreTeredoOnWindows)102 TEST(NetworkChangeNotifierTest, IgnoreTeredoOnWindows) {
103   NetworkInterfaceList list;
104   NetworkInterface interface_teredo;
105   interface_teredo.type = NetworkChangeNotifier::CONNECTION_ETHERNET;
106   interface_teredo.friendly_name = "Teredo Tunneling Pseudo-Interface";
107   list.push_back(interface_teredo);
108 
109 #if BUILDFLAG(IS_WIN)
110   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
111             NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
112 #else
113   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_ETHERNET,
114             NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
115 #endif
116 }
117 
TEST(NetworkChangeNotifierTest,IgnoreAirdropOnMac)118 TEST(NetworkChangeNotifierTest, IgnoreAirdropOnMac) {
119   NetworkInterfaceList list;
120   NetworkInterface interface_airdrop;
121   interface_airdrop.type = NetworkChangeNotifier::CONNECTION_ETHERNET;
122   interface_airdrop.name = "awdl0";
123   interface_airdrop.friendly_name = "awdl0";
124   interface_airdrop.address =
125       // Link-local IPv6 address
126       IPAddress(0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4);
127   list.push_back(interface_airdrop);
128 
129 #if BUILDFLAG(IS_APPLE)
130   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
131             NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
132 #else
133   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_ETHERNET,
134             NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
135 #endif
136 }
137 
TEST(NetworkChangeNotifierTest,IgnoreTunnelsOnMac)138 TEST(NetworkChangeNotifierTest, IgnoreTunnelsOnMac) {
139   NetworkInterfaceList list;
140   NetworkInterface interface_tunnel;
141   interface_tunnel.type = NetworkChangeNotifier::CONNECTION_ETHERNET;
142   interface_tunnel.name = "utun0";
143   interface_tunnel.friendly_name = "utun0";
144   interface_tunnel.address =
145       // Link-local IPv6 address
146       IPAddress(0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 2, 1);
147   list.push_back(interface_tunnel);
148 
149 #if BUILDFLAG(IS_APPLE)
150   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
151             NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
152 #else
153   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_ETHERNET,
154             NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
155 #endif
156 }
157 
TEST(NetworkChangeNotifierTest,IgnoreDisconnectedEthernetOnMac)158 TEST(NetworkChangeNotifierTest, IgnoreDisconnectedEthernetOnMac) {
159   NetworkInterfaceList list;
160   NetworkInterface interface_ethernet;
161   interface_ethernet.type = NetworkChangeNotifier::CONNECTION_ETHERNET;
162   interface_ethernet.name = "en5";
163   interface_ethernet.friendly_name = "en5";
164   interface_ethernet.address =
165       // Link-local IPv6 address
166       IPAddress(0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 2, 3);
167   list.push_back(interface_ethernet);
168 
169 #if BUILDFLAG(IS_APPLE)
170   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
171             NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
172 #else
173   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_ETHERNET,
174             NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
175 #endif
176 }
177 
TEST(NetworkChangeNotifierTest,IgnoreVMInterfaces)178 TEST(NetworkChangeNotifierTest, IgnoreVMInterfaces) {
179   NetworkInterfaceList list;
180   NetworkInterface interface_vmnet_linux;
181   interface_vmnet_linux.type = NetworkChangeNotifier::CONNECTION_ETHERNET;
182   interface_vmnet_linux.name = "vmnet1";
183   interface_vmnet_linux.friendly_name = "vmnet1";
184   list.push_back(interface_vmnet_linux);
185 
186   NetworkInterface interface_vmnet_win;
187   interface_vmnet_win.type = NetworkChangeNotifier::CONNECTION_ETHERNET;
188   interface_vmnet_win.name = "virtualdevice";
189   interface_vmnet_win.friendly_name = "VMware Network Adapter VMnet1";
190   list.push_back(interface_vmnet_win);
191 
192   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
193             NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
194 }
195 
TEST(NetworkChangeNotifierTest,GetConnectionSubtype)196 TEST(NetworkChangeNotifierTest, GetConnectionSubtype) {
197   // Call GetConnectionSubtype() and ensure that there is no crash.
198   NetworkChangeNotifier::GetConnectionSubtype();
199 }
200 
201 class NetworkChangeNotifierMockedTest : public TestWithTaskEnvironment {
202  protected:
203   test::ScopedMockNetworkChangeNotifier mock_notifier_;
204 };
205 
206 class TestDnsObserver : public NetworkChangeNotifier::DNSObserver {
207  public:
OnDNSChanged()208   void OnDNSChanged() override { ++dns_changed_calls_; }
209 
dns_changed_calls() const210   int dns_changed_calls() const { return dns_changed_calls_; }
211 
212  private:
213   int dns_changed_calls_ = 0;
214 };
215 
TEST_F(NetworkChangeNotifierMockedTest,TriggerNonSystemDnsChange)216 TEST_F(NetworkChangeNotifierMockedTest, TriggerNonSystemDnsChange) {
217   TestDnsObserver observer;
218   NetworkChangeNotifier::AddDNSObserver(&observer);
219 
220   ASSERT_EQ(0, observer.dns_changed_calls());
221 
222   NetworkChangeNotifier::TriggerNonSystemDnsChange();
223   base::RunLoop().RunUntilIdle();
224 
225   EXPECT_EQ(1, observer.dns_changed_calls());
226 
227   NetworkChangeNotifier::RemoveDNSObserver(&observer);
228 }
229 
TEST_F(NetworkChangeNotifierMockedTest,TriggerConnectionCostChange)230 TEST_F(NetworkChangeNotifierMockedTest, TriggerConnectionCostChange) {
231   TestConnectionCostObserver observer;
232   NetworkChangeNotifier::AddConnectionCostObserver(&observer);
233 
234   ASSERT_EQ(0u, observer.cost_changed_calls());
235 
236   NetworkChangeNotifier::NotifyObserversOfConnectionCostChangeForTests(
237       NetworkChangeNotifier::CONNECTION_COST_METERED);
238   base::RunLoop().RunUntilIdle();
239 
240   EXPECT_EQ(1u, observer.cost_changed_calls());
241   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_COST_METERED,
242             observer.cost_changed_inputs()[0]);
243 
244   NetworkChangeNotifier::RemoveConnectionCostObserver(&observer);
245   NetworkChangeNotifier::NotifyObserversOfConnectionCostChangeForTests(
246       NetworkChangeNotifier::CONNECTION_COST_UNMETERED);
247   base::RunLoop().RunUntilIdle();
248 
249   EXPECT_EQ(1u, observer.cost_changed_calls());
250 }
251 
TEST_F(NetworkChangeNotifierMockedTest,ConnectionCostDefaultsToCellular)252 TEST_F(NetworkChangeNotifierMockedTest, ConnectionCostDefaultsToCellular) {
253   mock_notifier_.mock_network_change_notifier()
254       ->SetUseDefaultConnectionCostImplementation(true);
255 
256   mock_notifier_.mock_network_change_notifier()->SetConnectionType(
257       NetworkChangeNotifier::CONNECTION_4G);
258   EXPECT_TRUE(NetworkChangeNotifier::IsConnectionCellular(
259       NetworkChangeNotifier::GetConnectionType()));
260   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_COST_METERED,
261             NetworkChangeNotifier::GetConnectionCost());
262 
263   mock_notifier_.mock_network_change_notifier()->SetConnectionType(
264       NetworkChangeNotifier::CONNECTION_WIFI);
265   EXPECT_FALSE(NetworkChangeNotifier::IsConnectionCellular(
266       NetworkChangeNotifier::GetConnectionType()));
267   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_COST_UNMETERED,
268             NetworkChangeNotifier::GetConnectionCost());
269 }
270 
271 class NetworkChangeNotifierConnectionCostTest : public TestWithTaskEnvironment {
272  public:
SetUp()273   void SetUp() override {
274     network_change_notifier_ = NetworkChangeNotifier::CreateIfNeeded();
275   }
276 
277  private:
278   // Allows creating a new NetworkChangeNotifier.  Must be created before
279   // |network_change_notifier_| and destroyed after it to avoid DCHECK failures.
280   NetworkChangeNotifier::DisableForTest disable_for_test_;
281   std::unique_ptr<NetworkChangeNotifier> network_change_notifier_;
282 };
283 
TEST_F(NetworkChangeNotifierConnectionCostTest,GetConnectionCost)284 TEST_F(NetworkChangeNotifierConnectionCostTest, GetConnectionCost) {
285   EXPECT_NE(NetworkChangeNotifier::ConnectionCost::CONNECTION_COST_UNKNOWN,
286             NetworkChangeNotifier::GetConnectionCost());
287 }
288 
TEST_F(NetworkChangeNotifierConnectionCostTest,AddObserver)289 TEST_F(NetworkChangeNotifierConnectionCostTest, AddObserver) {
290   TestConnectionCostObserver observer;
291   EXPECT_NO_FATAL_FAILURE(
292       NetworkChangeNotifier::AddConnectionCostObserver(&observer));
293   // RunUntilIdle because the secondary work resulting from adding an observer
294   // may be posted to a task queue.
295   base::RunLoop().RunUntilIdle();
296 }
297 
298 }  // namespace net
299