1 // Copyright (c) 2014 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 "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_with_task_environment.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 namespace net {
15 
16 // Note: This test is subject to the host's OS and network connection. This test
17 // is not future-proof. New standards will come about necessitating the need to
18 // alter the ranges of these tests.
TEST(NetworkChangeNotifierTest,NetMaxBandwidthRange)19 TEST(NetworkChangeNotifierTest, NetMaxBandwidthRange) {
20   NetworkChangeNotifier::ConnectionType connection_type =
21       NetworkChangeNotifier::CONNECTION_NONE;
22   double max_bandwidth = 0.0;
23   NetworkChangeNotifier::GetMaxBandwidthAndConnectionType(&max_bandwidth,
24                                                           &connection_type);
25 
26   // Always accept infinity as it's the default value if the bandwidth is
27   // unknown.
28   if (max_bandwidth == std::numeric_limits<double>::infinity()) {
29     EXPECT_NE(NetworkChangeNotifier::CONNECTION_NONE, connection_type);
30     return;
31   }
32 
33   switch (connection_type) {
34     case NetworkChangeNotifier::CONNECTION_UNKNOWN:
35       EXPECT_EQ(std::numeric_limits<double>::infinity(), max_bandwidth);
36       break;
37     case NetworkChangeNotifier::CONNECTION_ETHERNET:
38       EXPECT_GE(10.0, max_bandwidth);
39       EXPECT_LE(10000.0, max_bandwidth);
40       break;
41     case NetworkChangeNotifier::CONNECTION_WIFI:
42       EXPECT_GE(1.0, max_bandwidth);
43       EXPECT_LE(7000.0, max_bandwidth);
44       break;
45     case NetworkChangeNotifier::CONNECTION_2G:
46       EXPECT_GE(0.01, max_bandwidth);
47       EXPECT_LE(0.384, max_bandwidth);
48       break;
49     case NetworkChangeNotifier::CONNECTION_3G:
50       EXPECT_GE(2.0, max_bandwidth);
51       EXPECT_LE(42.0, max_bandwidth);
52       break;
53     case NetworkChangeNotifier::CONNECTION_4G:
54       EXPECT_GE(100.0, max_bandwidth);
55       EXPECT_LE(100.0, max_bandwidth);
56       break;
57     case NetworkChangeNotifier::CONNECTION_5G:
58       // TODO(crbug.com/1127134): Expect proper bounds once we have introduced
59       // subtypes for 5G connections.
60       EXPECT_EQ(std::numeric_limits<double>::infinity(), max_bandwidth);
61       break;
62     case NetworkChangeNotifier::CONNECTION_NONE:
63       EXPECT_EQ(0.0, max_bandwidth);
64       break;
65     case NetworkChangeNotifier::CONNECTION_BLUETOOTH:
66       EXPECT_GE(1.0, max_bandwidth);
67       EXPECT_LE(24.0, max_bandwidth);
68       break;
69   }
70 }
71 
TEST(NetworkChangeNotifierTest,ConnectionTypeFromInterfaceList)72 TEST(NetworkChangeNotifierTest, ConnectionTypeFromInterfaceList) {
73   NetworkInterfaceList list;
74 
75   // Test empty list.
76   EXPECT_EQ(NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list),
77             NetworkChangeNotifier::CONNECTION_NONE);
78 
79   for (int i = NetworkChangeNotifier::CONNECTION_UNKNOWN;
80        i <= NetworkChangeNotifier::CONNECTION_LAST; i++) {
81     // Check individual types.
82     NetworkInterface interface;
83     interface.type = static_cast<NetworkChangeNotifier::ConnectionType>(i);
84     list.clear();
85     list.push_back(interface);
86     EXPECT_EQ(NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list), i);
87     // Check two types.
88     for (int j = NetworkChangeNotifier::CONNECTION_UNKNOWN;
89          j <= NetworkChangeNotifier::CONNECTION_LAST; j++) {
90       list.clear();
91       interface.type = static_cast<NetworkChangeNotifier::ConnectionType>(i);
92       list.push_back(interface);
93       interface.type = static_cast<NetworkChangeNotifier::ConnectionType>(j);
94       list.push_back(interface);
95       EXPECT_EQ(NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list),
96                 i == j ? i : NetworkChangeNotifier::CONNECTION_UNKNOWN);
97     }
98   }
99 }
100 
TEST(NetworkChangeNotifierTest,IgnoreTeredoOnWindows)101 TEST(NetworkChangeNotifierTest, IgnoreTeredoOnWindows) {
102   NetworkInterfaceList list;
103   NetworkInterface interface_teredo;
104   interface_teredo.type = NetworkChangeNotifier::CONNECTION_ETHERNET;
105   interface_teredo.friendly_name = "Teredo Tunneling Pseudo-Interface";
106   list.push_back(interface_teredo);
107 
108 #if defined(OS_WIN)
109   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
110             NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
111 #else
112   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_ETHERNET,
113             NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
114 #endif
115 }
116 
TEST(NetworkChangeNotifierTest,IgnoreAirdropOnMac)117 TEST(NetworkChangeNotifierTest, IgnoreAirdropOnMac) {
118   NetworkInterfaceList list;
119   NetworkInterface interface_airdrop;
120   interface_airdrop.type = NetworkChangeNotifier::CONNECTION_ETHERNET;
121   interface_airdrop.name = "awdl0";
122   interface_airdrop.friendly_name = "awdl0";
123   interface_airdrop.address =
124       // Link-local IPv6 address
125       IPAddress({0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4});
126   list.push_back(interface_airdrop);
127 
128 #if defined(OS_APPLE)
129   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
130             NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
131 #else
132   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_ETHERNET,
133             NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
134 #endif
135 }
136 
TEST(NetworkChangeNotifierTest,IgnoreTunnelsOnMac)137 TEST(NetworkChangeNotifierTest, IgnoreTunnelsOnMac) {
138   NetworkInterfaceList list;
139   NetworkInterface interface_tunnel;
140   interface_tunnel.type = NetworkChangeNotifier::CONNECTION_ETHERNET;
141   interface_tunnel.name = "utun0";
142   interface_tunnel.friendly_name = "utun0";
143   interface_tunnel.address =
144       // Link-local IPv6 address
145       IPAddress({0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 2, 1});
146   list.push_back(interface_tunnel);
147 
148 #if defined(OS_APPLE)
149   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
150             NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
151 #else
152   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_ETHERNET,
153             NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
154 #endif
155 }
156 
TEST(NetworkChangeNotifierTest,IgnoreDisconnectedEthernetOnMac)157 TEST(NetworkChangeNotifierTest, IgnoreDisconnectedEthernetOnMac) {
158   NetworkInterfaceList list;
159   NetworkInterface interface_ethernet;
160   interface_ethernet.type = NetworkChangeNotifier::CONNECTION_ETHERNET;
161   interface_ethernet.name = "en5";
162   interface_ethernet.friendly_name = "en5";
163   interface_ethernet.address =
164       // Link-local IPv6 address
165       IPAddress({0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 2, 3});
166   list.push_back(interface_ethernet);
167 
168 #if defined(OS_APPLE)
169   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
170             NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
171 #else
172   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_ETHERNET,
173             NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
174 #endif
175 }
176 
TEST(NetworkChangeNotifierTest,IgnoreVMInterfaces)177 TEST(NetworkChangeNotifierTest, IgnoreVMInterfaces) {
178   NetworkInterfaceList list;
179   NetworkInterface interface_vmnet_linux;
180   interface_vmnet_linux.type = NetworkChangeNotifier::CONNECTION_ETHERNET;
181   interface_vmnet_linux.name = "vmnet1";
182   interface_vmnet_linux.friendly_name = "vmnet1";
183   list.push_back(interface_vmnet_linux);
184 
185   NetworkInterface interface_vmnet_win;
186   interface_vmnet_win.type = NetworkChangeNotifier::CONNECTION_ETHERNET;
187   interface_vmnet_win.name = "virtualdevice";
188   interface_vmnet_win.friendly_name = "VMware Network Adapter VMnet1";
189   list.push_back(interface_vmnet_win);
190 
191   EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
192             NetworkChangeNotifier::ConnectionTypeFromInterfaceList(list));
193 }
194 
TEST(NetworkChangeNotifierTest,GetConnectionSubtype)195 TEST(NetworkChangeNotifierTest, GetConnectionSubtype) {
196   // Call GetConnectionSubtype() and ensure that there is no crash.
197   NetworkChangeNotifier::GetConnectionSubtype();
198 }
199 
200 class NetworkChangeNotifierMockedTest : public TestWithTaskEnvironment {
201  private:
202   test::ScopedMockNetworkChangeNotifier mock_notifier_;
203 };
204 
205 class TestDnsObserver : public NetworkChangeNotifier::DNSObserver {
206  public:
OnDNSChanged()207   void OnDNSChanged() override { ++dns_changed_calls_; }
208 
dns_changed_calls() const209   int dns_changed_calls() const { return dns_changed_calls_; }
210 
211  private:
212   int dns_changed_calls_ = 0;
213 };
214 
TEST_F(NetworkChangeNotifierMockedTest,TriggerNonSystemDnsChange)215 TEST_F(NetworkChangeNotifierMockedTest, TriggerNonSystemDnsChange) {
216   TestDnsObserver observer;
217   NetworkChangeNotifier::AddDNSObserver(&observer);
218 
219   ASSERT_EQ(0, observer.dns_changed_calls());
220 
221   NetworkChangeNotifier::TriggerNonSystemDnsChange();
222   base::RunLoop().RunUntilIdle();
223 
224   EXPECT_EQ(1, observer.dns_changed_calls());
225 
226   NetworkChangeNotifier::RemoveDNSObserver(&observer);
227 }
228 
229 }  // namespace net
230