blob: 0500330ade4e95e916616bba382728b4e5f0d24c [file] [log] [blame]
Thieu Le3426c8f2012-01-11 17:35:11 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Chris Masone9be4a9d2011-05-16 15:44:09 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Darin Petkov633ac6f2011-07-08 13:56:13 -07004
Chris Masone2aa97072011-08-09 17:35:08 -07005#include "shill/device_info.h"
6
Chris Masone9be4a9d2011-05-16 15:44:09 -07007#include <glib.h>
Darin Petkov633ac6f2011-07-08 13:56:13 -07008#include <sys/socket.h>
Darin Petkove6193c02011-08-11 12:42:40 -07009#include <linux/if.h>
Paul Stewartca876ee2012-04-21 08:55:58 -070010#include <linux/if_tun.h>
Darin Petkov633ac6f2011-07-08 13:56:13 -070011#include <linux/netlink.h> // Needs typedefs from sys/socket.h.
12#include <linux/rtnetlink.h>
Paul Stewartca876ee2012-04-21 08:55:58 -070013#include <net/if_arp.h>
Chris Masone9be4a9d2011-05-16 15:44:09 -070014
Thieu Le8f1c8352012-04-16 11:02:12 -070015#include <base/file_util.h>
Chris Masone9be4a9d2011-05-16 15:44:09 -070016#include <base/logging.h>
17#include <base/memory/ref_counted.h>
18#include <base/message_loop.h>
Thieu Le8f1c8352012-04-16 11:02:12 -070019#include <base/scoped_temp_dir.h>
Eric Shienbrood3e20a232012-02-16 11:35:56 -050020#include <base/stl_util.h>
Paul Stewartca876ee2012-04-21 08:55:58 -070021#include <base/string_number_conversions.h>
Chris Masone9be4a9d2011-05-16 15:44:09 -070022#include <gtest/gtest.h>
23#include <gmock/gmock.h>
24
Paul Stewart9a908082011-08-31 12:18:48 -070025#include "shill/ip_address.h"
Paul Stewartb50f0b92011-05-16 16:31:42 -070026#include "shill/manager.h"
Chris Masone46eaaf52011-05-24 13:08:30 -070027#include "shill/mock_control.h"
Darin Petkovafa6fc42011-06-21 16:21:08 -070028#include "shill/mock_glib.h"
Chris Masone2ae797d2011-08-23 20:41:00 -070029#include "shill/mock_manager.h"
Thieu Le3426c8f2012-01-11 17:35:11 -080030#include "shill/mock_metrics.h"
Paul Stewart8c116a92012-05-02 18:30:03 -070031#include "shill/mock_modem_info.h"
32#include "shill/mock_routing_table.h"
Paul Stewart9a908082011-08-31 12:18:48 -070033#include "shill/mock_rtnl_handler.h"
Darin Petkov633ac6f2011-07-08 13:56:13 -070034#include "shill/mock_sockets.h"
Paul Stewart8c116a92012-05-02 18:30:03 -070035#include "shill/mock_vpn_provider.h"
Darin Petkove4b27022012-05-16 13:28:50 +020036#include "shill/mock_wimax_provider.h"
Chris Masone2aa97072011-08-09 17:35:08 -070037#include "shill/rtnl_message.h"
Darin Petkovc63dcf02012-05-24 11:51:43 +020038#include "shill/wimax.h"
Chris Masone9be4a9d2011-05-16 15:44:09 -070039
Eric Shienbrood3e20a232012-02-16 11:35:56 -050040using base::Callback;
Darin Petkove6193c02011-08-11 12:42:40 -070041using std::map;
Darin Petkov633ac6f2011-07-08 13:56:13 -070042using std::string;
Paul Stewart9a908082011-08-31 12:18:48 -070043using std::vector;
Darin Petkov633ac6f2011-07-08 13:56:13 -070044using testing::_;
Paul Stewart8c116a92012-05-02 18:30:03 -070045using testing::Mock;
Darin Petkov633ac6f2011-07-08 13:56:13 -070046using testing::Return;
Paul Stewart9a908082011-08-31 12:18:48 -070047using testing::StrictMock;
Darin Petkov633ac6f2011-07-08 13:56:13 -070048using testing::Test;
49
Chris Masone9be4a9d2011-05-16 15:44:09 -070050namespace shill {
Darin Petkov633ac6f2011-07-08 13:56:13 -070051
52class TestEventDispatcher : public EventDispatcher {
53 public:
Paul Stewart26b327e2011-10-19 11:38:09 -070054 virtual IOHandler *CreateInputHandler(
mukesh agrawal1830fa12011-09-26 14:31:40 -070055 int /*fd*/,
Eric Shienbrood3e20a232012-02-16 11:35:56 -050056 const Callback<void(InputData*)> &/*callback*/) {
Darin Petkov633ac6f2011-07-08 13:56:13 -070057 return NULL;
58 }
59};
Chris Masone9be4a9d2011-05-16 15:44:09 -070060
61class DeviceInfoTest : public Test {
62 public:
63 DeviceInfoTest()
Thieu Le3426c8f2012-01-11 17:35:11 -080064 : manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
65 device_info_(&control_interface_, &dispatcher_, &metrics_, &manager_) {
Chris Masone9be4a9d2011-05-16 15:44:09 -070066 }
Paul Stewartca876ee2012-04-21 08:55:58 -070067 virtual ~DeviceInfoTest() {}
Darin Petkov633ac6f2011-07-08 13:56:13 -070068
Paul Stewart9a908082011-08-31 12:18:48 -070069 virtual void SetUp() {
70 device_info_.rtnl_handler_ = &rtnl_handler_;
Paul Stewart8c116a92012-05-02 18:30:03 -070071 device_info_.routing_table_ = &routing_table_;
Paul Stewart9a908082011-08-31 12:18:48 -070072 }
73
Paul Stewart8c116a92012-05-02 18:30:03 -070074 IPAddress CreateInterfaceAddress() {
75 // Create an IP address entry (as if left-over from a previous connection
76 // manager).
77 IPAddress address(IPAddress::kFamilyIPv4);
78 EXPECT_TRUE(address.SetAddressFromString(kTestIPAddress0));
79 address.set_prefix(kTestIPAddressPrefix0);
80 vector<DeviceInfo::AddressData> &addresses =
81 device_info_.infos_[kTestDeviceIndex].ip_addresses;
82 addresses.push_back(DeviceInfo::AddressData(address, 0, RT_SCOPE_UNIVERSE));
83 EXPECT_EQ(1, addresses.size());
84 return address;
85 }
86
87 DeviceRefPtr CreateDevice(const std::string &link_name,
88 const std::string &address,
89 int interface_index,
90 Technology::Identifier technology) {
91 return device_info_.CreateDevice(link_name, address, interface_index,
92 technology);
93 }
94
95
Paul Stewarta3c56f92011-05-26 07:08:52 -070096 protected:
Chris Masoneb2e326b2011-07-12 13:28:51 -070097 static const int kTestDeviceIndex;
Darin Petkov633ac6f2011-07-08 13:56:13 -070098 static const char kTestDeviceName[];
Paul Stewart9a908082011-08-31 12:18:48 -070099 static const char kTestMACAddress[];
100 static const char kTestIPAddress0[];
101 static const int kTestIPAddressPrefix0;
102 static const char kTestIPAddress1[];
103 static const int kTestIPAddressPrefix1;
104 static const char kTestIPAddress2[];
105 static const char kTestIPAddress3[];
106 static const char kTestIPAddress4[];
Darin Petkov633ac6f2011-07-08 13:56:13 -0700107
Paul Stewart9a908082011-08-31 12:18:48 -0700108 RTNLMessage *BuildLinkMessage(RTNLMessage::Mode mode);
Paul Stewarte81eb702012-04-11 15:04:53 -0700109 RTNLMessage *BuildLinkMessageWithInterfaceName(RTNLMessage::Mode mode,
110 const string &interface_name);
Paul Stewart9a908082011-08-31 12:18:48 -0700111 RTNLMessage *BuildAddressMessage(RTNLMessage::Mode mode,
112 const IPAddress &address,
113 unsigned char flags,
114 unsigned char scope);
Chris Masone2aa97072011-08-09 17:35:08 -0700115 void SendMessageToDeviceInfo(const RTNLMessage &message);
Darin Petkov633ac6f2011-07-08 13:56:13 -0700116
Darin Petkovafa6fc42011-06-21 16:21:08 -0700117 MockGLib glib_;
Chris Masone46eaaf52011-05-24 13:08:30 -0700118 MockControl control_interface_;
Thieu Le3426c8f2012-01-11 17:35:11 -0800119 MockMetrics metrics_;
Paul Stewart9a908082011-08-31 12:18:48 -0700120 StrictMock<MockManager> manager_;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700121 DeviceInfo device_info_;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700122 TestEventDispatcher dispatcher_;
Paul Stewart8c116a92012-05-02 18:30:03 -0700123 MockRoutingTable routing_table_;
Paul Stewart9a908082011-08-31 12:18:48 -0700124 StrictMock<MockRTNLHandler> rtnl_handler_;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700125};
126
Chris Masoneb2e326b2011-07-12 13:28:51 -0700127const int DeviceInfoTest::kTestDeviceIndex = 123456;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700128const char DeviceInfoTest::kTestDeviceName[] = "test-device";
Paul Stewart9a908082011-08-31 12:18:48 -0700129const char DeviceInfoTest::kTestMACAddress[] = {
Darin Petkove3e1cfa2011-08-11 13:41:17 -0700130 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
Paul Stewart9a908082011-08-31 12:18:48 -0700131const char DeviceInfoTest::kTestIPAddress0[] = "192.168.1.1";
132const int DeviceInfoTest::kTestIPAddressPrefix0 = 24;
133const char DeviceInfoTest::kTestIPAddress1[] = "fe80::1aa9:5ff:abcd:1234";
134const int DeviceInfoTest::kTestIPAddressPrefix1 = 64;
135const char DeviceInfoTest::kTestIPAddress2[] = "fe80::1aa9:5ff:abcd:1235";
136const char DeviceInfoTest::kTestIPAddress3[] = "fe80::1aa9:5ff:abcd:1236";
137const char DeviceInfoTest::kTestIPAddress4[] = "fe80::1aa9:5ff:abcd:1237";
Chris Masone9be4a9d2011-05-16 15:44:09 -0700138
Paul Stewarte81eb702012-04-11 15:04:53 -0700139RTNLMessage *DeviceInfoTest::BuildLinkMessageWithInterfaceName(
140 RTNLMessage::Mode mode, const string &interface_name) {
Paul Stewart9a908082011-08-31 12:18:48 -0700141 RTNLMessage *message = new RTNLMessage(
142 RTNLMessage::kTypeLink,
143 mode,
144 0,
145 0,
146 0,
147 kTestDeviceIndex,
Paul Stewart7355ce12011-09-02 10:47:01 -0700148 IPAddress::kFamilyIPv4);
Chris Masone2aa97072011-08-09 17:35:08 -0700149 message->SetAttribute(static_cast<uint16>(IFLA_IFNAME),
Paul Stewarte81eb702012-04-11 15:04:53 -0700150 ByteString(interface_name, true));
Paul Stewart9a908082011-08-31 12:18:48 -0700151 ByteString test_address(kTestMACAddress, sizeof(kTestMACAddress));
Chris Masone626719f2011-08-18 16:58:48 -0700152 message->SetAttribute(IFLA_ADDRESS, test_address);
Chris Masone2aa97072011-08-09 17:35:08 -0700153 return message;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700154}
155
Paul Stewarte81eb702012-04-11 15:04:53 -0700156RTNLMessage *DeviceInfoTest::BuildLinkMessage(RTNLMessage::Mode mode) {
157 return BuildLinkMessageWithInterfaceName(mode, kTestDeviceName);
158}
159
Paul Stewart9a908082011-08-31 12:18:48 -0700160RTNLMessage *DeviceInfoTest::BuildAddressMessage(RTNLMessage::Mode mode,
161 const IPAddress &address,
162 unsigned char flags,
163 unsigned char scope) {
164 RTNLMessage *message = new RTNLMessage(
165 RTNLMessage::kTypeAddress,
166 mode,
167 0,
168 0,
169 0,
170 kTestDeviceIndex,
171 address.family());
172 message->SetAttribute(IFA_ADDRESS, address.address());
173 message->set_address_status(
174 RTNLMessage::AddressStatus(address.prefix(), flags, scope));
175 return message;
176}
177
Chris Masone2aa97072011-08-09 17:35:08 -0700178void DeviceInfoTest::SendMessageToDeviceInfo(const RTNLMessage &message) {
Paul Stewart9a908082011-08-31 12:18:48 -0700179 if (message.type() == RTNLMessage::kTypeLink) {
180 device_info_.LinkMsgHandler(message);
181 } else if (message.type() == RTNLMessage::kTypeAddress) {
182 device_info_.AddressMsgHandler(message);
183 } else {
184 NOTREACHED();
185 }
186}
187
188MATCHER_P(IsIPAddress, address, "") {
189 // NB: IPAddress objects don't support the "==" operator as per style, so
190 // we need a custom matcher.
191 return address.Equals(arg);
Darin Petkov633ac6f2011-07-08 13:56:13 -0700192}
193
Paul Stewart8c116a92012-05-02 18:30:03 -0700194TEST_F(DeviceInfoTest, StartStop) {
195 EXPECT_FALSE(device_info_.link_listener_.get());
196 EXPECT_FALSE(device_info_.address_listener_.get());
197 EXPECT_TRUE(device_info_.infos_.empty());
198
199 EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestLink |
200 RTNLHandler::kRequestAddr));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700201 device_info_.Start();
Paul Stewart8c116a92012-05-02 18:30:03 -0700202 EXPECT_TRUE(device_info_.link_listener_.get());
203 EXPECT_TRUE(device_info_.address_listener_.get());
204 EXPECT_TRUE(device_info_.infos_.empty());
205 Mock::VerifyAndClearExpectations(&rtnl_handler_);
206
207 CreateInterfaceAddress();
208 EXPECT_FALSE(device_info_.infos_.empty());
209
210 device_info_.Stop();
211 EXPECT_FALSE(device_info_.link_listener_.get());
212 EXPECT_FALSE(device_info_.address_listener_.get());
213 EXPECT_TRUE(device_info_.infos_.empty());
214}
215
216TEST_F(DeviceInfoTest, DeviceEnumeration) {
Paul Stewart9a908082011-08-31 12:18:48 -0700217 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
Darin Petkove6193c02011-08-11 12:42:40 -0700218 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_LOWER_UP, 0));
219 EXPECT_FALSE(device_info_.GetDevice(kTestDeviceIndex).get());
Darin Petkovf8046b82012-04-24 16:29:23 +0200220 EXPECT_EQ(-1, device_info_.GetIndex(kTestDeviceName));
Darin Petkove6193c02011-08-11 12:42:40 -0700221 SendMessageToDeviceInfo(*message);
222 EXPECT_TRUE(device_info_.GetDevice(kTestDeviceIndex).get());
223 unsigned int flags = 0;
224 EXPECT_TRUE(device_info_.GetFlags(kTestDeviceIndex, &flags));
225 EXPECT_EQ(IFF_LOWER_UP, flags);
Darin Petkove3e1cfa2011-08-11 13:41:17 -0700226 ByteString address;
Paul Stewart32852962011-08-30 14:06:53 -0700227 EXPECT_TRUE(device_info_.GetMACAddress(kTestDeviceIndex, &address));
Darin Petkove3e1cfa2011-08-11 13:41:17 -0700228 EXPECT_FALSE(address.IsEmpty());
Paul Stewart9a908082011-08-31 12:18:48 -0700229 EXPECT_TRUE(address.Equals(ByteString(kTestMACAddress,
230 sizeof(kTestMACAddress))));
Darin Petkovf8046b82012-04-24 16:29:23 +0200231 EXPECT_EQ(kTestDeviceIndex, device_info_.GetIndex(kTestDeviceName));
Paul Stewarta3c56f92011-05-26 07:08:52 -0700232
Paul Stewart9a908082011-08-31 12:18:48 -0700233 message.reset(BuildLinkMessage(RTNLMessage::kModeAdd));
Darin Petkove6193c02011-08-11 12:42:40 -0700234 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_UP | IFF_RUNNING, 0));
235 SendMessageToDeviceInfo(*message);
236 EXPECT_TRUE(device_info_.GetFlags(kTestDeviceIndex, &flags));
237 EXPECT_EQ(IFF_UP | IFF_RUNNING, flags);
Paul Stewartb50f0b92011-05-16 16:31:42 -0700238
Paul Stewart9a908082011-08-31 12:18:48 -0700239 message.reset(BuildLinkMessage(RTNLMessage::kModeDelete));
Paul Stewart8c116a92012-05-02 18:30:03 -0700240 EXPECT_CALL(manager_, DeregisterDevice(_)).Times(1);
Darin Petkove6193c02011-08-11 12:42:40 -0700241 SendMessageToDeviceInfo(*message);
242 EXPECT_FALSE(device_info_.GetDevice(kTestDeviceIndex).get());
243 EXPECT_FALSE(device_info_.GetFlags(kTestDeviceIndex, NULL));
Darin Petkovf8046b82012-04-24 16:29:23 +0200244 EXPECT_EQ(-1, device_info_.GetIndex(kTestDeviceName));
Paul Stewart8c116a92012-05-02 18:30:03 -0700245}
Paul Stewarta3c56f92011-05-26 07:08:52 -0700246
Paul Stewart8c116a92012-05-02 18:30:03 -0700247TEST_F(DeviceInfoTest, CreateDeviceCellular) {
248 IPAddress address = CreateInterfaceAddress();
249
250 // A cellular device should be offered to ModemInfo.
251 StrictMock<MockModemInfo> modem_info;
252 EXPECT_CALL(manager_, modem_info()).WillOnce(Return(&modem_info));
253 EXPECT_CALL(modem_info, OnDeviceInfoAvailable(kTestDeviceName)).Times(1);
254 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
255 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
256 IsIPAddress(address)));
257 EXPECT_FALSE(CreateDevice(
258 kTestDeviceName, "address", kTestDeviceIndex, Technology::kCellular));
259}
260
Darin Petkove4b27022012-05-16 13:28:50 +0200261TEST_F(DeviceInfoTest, CreateDeviceWiMax) {
262 IPAddress address = CreateInterfaceAddress();
263
264 // A WiMax device should be offered to WiMaxProvider.
265 StrictMock<MockWiMaxProvider> wimax_provider;
266 EXPECT_CALL(manager_, wimax_provider()).WillOnce(Return(&wimax_provider));
267 EXPECT_CALL(wimax_provider, OnDeviceInfoAvailable(kTestDeviceName)).Times(1);
268 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
269 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
270 IsIPAddress(address)));
271 EXPECT_FALSE(CreateDevice(
272 kTestDeviceName, "address", kTestDeviceIndex, Technology::kWiMax));
273}
274
Paul Stewart8c116a92012-05-02 18:30:03 -0700275TEST_F(DeviceInfoTest, CreateDeviceEthernet) {
276 IPAddress address = CreateInterfaceAddress();
277
278 // An Ethernet device should cause routes and addresses to be flushed.
279 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
280 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
281 IsIPAddress(address)));
282 DeviceRefPtr device = CreateDevice(
283 kTestDeviceName, "address", kTestDeviceIndex, Technology::kEthernet);
284 EXPECT_TRUE(device);
285 Mock::VerifyAndClearExpectations(&routing_table_);
286 Mock::VerifyAndClearExpectations(&rtnl_handler_);
287
288 // The Ethernet device destructor notifies the manager.
289 EXPECT_CALL(manager_, UpdateEnabledTechnologies()).Times(1);
290 device = NULL;
291}
292
293TEST_F(DeviceInfoTest, CreateDeviceVirtioEthernet) {
294 IPAddress address = CreateInterfaceAddress();
295
296 // VirtioEthernet is identical to Ethernet from the perspective of this test.
297 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
298 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
299 IsIPAddress(address)));
300 DeviceRefPtr device = CreateDevice(
301 kTestDeviceName, "address", kTestDeviceIndex,
302 Technology::kVirtioEthernet);
303 EXPECT_TRUE(device);
304 Mock::VerifyAndClearExpectations(&routing_table_);
305 Mock::VerifyAndClearExpectations(&rtnl_handler_);
306
307 // The Ethernet device destructor notifies the manager.
308 EXPECT_CALL(manager_, UpdateEnabledTechnologies()).Times(1);
309 device = NULL;
310}
311
312TEST_F(DeviceInfoTest, CreateDeviceWiFi) {
313 IPAddress address = CreateInterfaceAddress();
314
315 // WiFi looks a lot like Ethernet too.
316 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
317 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
318 IsIPAddress(address)));
319 EXPECT_TRUE(CreateDevice(
320 kTestDeviceName, "address", kTestDeviceIndex, Technology::kWifi));
321}
322
323TEST_F(DeviceInfoTest, CreateDeviceTunnelAccepted) {
324 IPAddress address = CreateInterfaceAddress();
325
326 // A VPN device should be offered to VPNProvider.
327 StrictMock<MockVPNProvider> vpn_provider;
328 EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&vpn_provider));
329 EXPECT_CALL(vpn_provider,
330 OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
331 .WillOnce(Return(true));
332 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
333 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
334 IsIPAddress(address)));
335 EXPECT_CALL(rtnl_handler_, RemoveInterface(_)).Times(0);
336 EXPECT_FALSE(CreateDevice(
337 kTestDeviceName, "address", kTestDeviceIndex, Technology::kTunnel));
338}
339
340TEST_F(DeviceInfoTest, CreateDeviceTunnelRejected) {
341 IPAddress address = CreateInterfaceAddress();
342
343 // A VPN device should be offered to VPNProvider.
344 StrictMock<MockVPNProvider> vpn_provider;
345 EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&vpn_provider));
346 EXPECT_CALL(vpn_provider,
347 OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
348 .WillOnce(Return(false));
349 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
350 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
351 IsIPAddress(address)));
352 // Since the device was rejected by the VPNProvider, DeviceInfo will
353 // remove the interface.
354 EXPECT_CALL(rtnl_handler_, RemoveInterface(kTestDeviceIndex)).Times(1);
355 EXPECT_FALSE(CreateDevice(
356 kTestDeviceName, "address", kTestDeviceIndex, Technology::kTunnel));
357}
358
359TEST_F(DeviceInfoTest, CreateDevicePPP) {
360 IPAddress address = CreateInterfaceAddress();
361
362 // A VPN device should be offered to VPNProvider.
363 StrictMock<MockVPNProvider> vpn_provider;
364 EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&vpn_provider));
365 EXPECT_CALL(vpn_provider,
366 OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
367 .WillOnce(Return(false));
368 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
369 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
370 IsIPAddress(address)));
371 // We do not remove PPP interfaces even if the provider does not accept it.
372 EXPECT_CALL(rtnl_handler_, RemoveInterface(_)).Times(0);
373 EXPECT_FALSE(CreateDevice(
374 kTestDeviceName, "address", kTestDeviceIndex, Technology::kPPP));
375}
376
377TEST_F(DeviceInfoTest, CreateDeviceLoopback) {
378 // A loopback device should be brought up, and nothing else done to it.
379 EXPECT_CALL(routing_table_, FlushRoutes(_)).Times(0);
380 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(_, _)).Times(0);
381 EXPECT_CALL(rtnl_handler_,
382 SetInterfaceFlags(kTestDeviceIndex, IFF_UP, IFF_UP)).Times(1);
383 EXPECT_FALSE(CreateDevice(
384 kTestDeviceName, "address", kTestDeviceIndex, Technology::kLoopback));
385}
386
387TEST_F(DeviceInfoTest, CreateDeviceUnknown) {
388 IPAddress address = CreateInterfaceAddress();
389
390 // An unknown (blacklisted, unhandled, etc) device won't be flushed or
391 // registered.
392 EXPECT_CALL(routing_table_, FlushRoutes(_)).Times(0);
393 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(_, _)).Times(0);
394 EXPECT_TRUE(CreateDevice(
395 kTestDeviceName, "address", kTestDeviceIndex, Technology::kUnknown));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700396}
397
mukesh agrawal8f317b62011-07-15 11:53:23 -0700398TEST_F(DeviceInfoTest, DeviceBlackList) {
399 device_info_.AddDeviceToBlackList(kTestDeviceName);
Paul Stewart9a908082011-08-31 12:18:48 -0700400 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
Darin Petkove6193c02011-08-11 12:42:40 -0700401 SendMessageToDeviceInfo(*message);
mukesh agrawal8f317b62011-07-15 11:53:23 -0700402
Darin Petkove6193c02011-08-11 12:42:40 -0700403 DeviceRefPtr device = device_info_.GetDevice(kTestDeviceIndex);
404 ASSERT_TRUE(device.get());
Paul Stewartfdd16072011-09-16 12:41:35 -0700405 EXPECT_TRUE(device->TechnologyIs(Technology::kBlacklisted));
mukesh agrawal8f317b62011-07-15 11:53:23 -0700406}
407
Paul Stewart9a908082011-08-31 12:18:48 -0700408TEST_F(DeviceInfoTest, DeviceAddressList) {
Paul Stewart9a908082011-08-31 12:18:48 -0700409 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
410 SendMessageToDeviceInfo(*message);
411
412 vector<DeviceInfo::AddressData> addresses;
413 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
414 EXPECT_TRUE(addresses.empty());
415
416 // Add an address to the device address list
Paul Stewart7355ce12011-09-02 10:47:01 -0700417 IPAddress ip_address0(IPAddress::kFamilyIPv4);
Paul Stewart9a908082011-08-31 12:18:48 -0700418 EXPECT_TRUE(ip_address0.SetAddressFromString(kTestIPAddress0));
419 ip_address0.set_prefix(kTestIPAddressPrefix0);
420 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address0, 0, 0));
421 SendMessageToDeviceInfo(*message);
422 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
423 EXPECT_EQ(1, addresses.size());
424 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
425
426 // Re-adding the same address shouldn't cause the address list to change
427 SendMessageToDeviceInfo(*message);
428 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
429 EXPECT_EQ(1, addresses.size());
430 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
431
432 // Adding a new address should expand the list
Paul Stewart7355ce12011-09-02 10:47:01 -0700433 IPAddress ip_address1(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700434 EXPECT_TRUE(ip_address1.SetAddressFromString(kTestIPAddress1));
435 ip_address1.set_prefix(kTestIPAddressPrefix1);
436 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address1, 0, 0));
437 SendMessageToDeviceInfo(*message);
438 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
439 EXPECT_EQ(2, addresses.size());
440 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
441 EXPECT_TRUE(ip_address1.Equals(addresses[1].address));
442
443 // Deleting an address should reduce the list
444 message.reset(BuildAddressMessage(RTNLMessage::kModeDelete,
445 ip_address0,
446 0,
447 0));
448 SendMessageToDeviceInfo(*message);
449 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
450 EXPECT_EQ(1, addresses.size());
451 EXPECT_TRUE(ip_address1.Equals(addresses[0].address));
452
453 // Delete last item
454 message.reset(BuildAddressMessage(RTNLMessage::kModeDelete,
455 ip_address1,
456 0,
457 0));
458 SendMessageToDeviceInfo(*message);
459 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
460 EXPECT_TRUE(addresses.empty());
461
462 // Delete device
463 message.reset(BuildLinkMessage(RTNLMessage::kModeDelete));
Paul Stewart8c116a92012-05-02 18:30:03 -0700464 EXPECT_CALL(manager_, DeregisterDevice(_)).Times(1);
Paul Stewart9a908082011-08-31 12:18:48 -0700465 SendMessageToDeviceInfo(*message);
466
467 // Should be able to handle message for interface that doesn't exist
468 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address0, 0, 0));
469 SendMessageToDeviceInfo(*message);
470 EXPECT_FALSE(device_info_.GetDevice(kTestDeviceIndex).get());
Paul Stewart9a908082011-08-31 12:18:48 -0700471}
472
473TEST_F(DeviceInfoTest, FlushAddressList) {
Paul Stewart9a908082011-08-31 12:18:48 -0700474 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
475 SendMessageToDeviceInfo(*message);
476
Paul Stewart7355ce12011-09-02 10:47:01 -0700477 IPAddress address1(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700478 EXPECT_TRUE(address1.SetAddressFromString(kTestIPAddress1));
479 address1.set_prefix(kTestIPAddressPrefix1);
480 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
481 address1,
482 0,
483 RT_SCOPE_UNIVERSE));
484 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700485 IPAddress address2(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700486 EXPECT_TRUE(address2.SetAddressFromString(kTestIPAddress2));
487 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
488 address2,
489 IFA_F_TEMPORARY,
490 RT_SCOPE_UNIVERSE));
491 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700492 IPAddress address3(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700493 EXPECT_TRUE(address3.SetAddressFromString(kTestIPAddress3));
494 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
495 address3,
496 0,
497 RT_SCOPE_LINK));
498 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700499 IPAddress address4(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700500 EXPECT_TRUE(address4.SetAddressFromString(kTestIPAddress4));
501 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
502 address4,
503 IFA_F_PERMANENT,
504 RT_SCOPE_UNIVERSE));
505 SendMessageToDeviceInfo(*message);
506
507 // DeviceInfo now has 4 addresses associated with it, but only two of
508 // them are valid for flush.
509 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
510 IsIPAddress(address1)));
511 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
512 IsIPAddress(address2)));
513 device_info_.FlushAddresses(kTestDeviceIndex);
Paul Stewart9a908082011-08-31 12:18:48 -0700514}
515
Thieu Leb27beee2012-04-20 09:19:06 -0700516TEST_F(DeviceInfoTest, HasSubdir) {
Thieu Le8f1c8352012-04-16 11:02:12 -0700517 ScopedTempDir temp_dir;
518 EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
Thieu Leb27beee2012-04-20 09:19:06 -0700519 EXPECT_TRUE(file_util::CreateDirectory(temp_dir.path().Append("child1")));
520 FilePath child2 = temp_dir.path().Append("child2");
521 EXPECT_TRUE(file_util::CreateDirectory(child2));
522 FilePath grandchild = child2.Append("grandchild");
Thieu Le8f1c8352012-04-16 11:02:12 -0700523 EXPECT_TRUE(file_util::CreateDirectory(grandchild));
524 EXPECT_TRUE(file_util::CreateDirectory(grandchild.Append("greatgrandchild")));
Thieu Leb27beee2012-04-20 09:19:06 -0700525 EXPECT_TRUE(DeviceInfo::HasSubdir(temp_dir.path(),
526 FilePath("grandchild")));
527 EXPECT_TRUE(DeviceInfo::HasSubdir(temp_dir.path(),
528 FilePath("greatgrandchild")));
529 EXPECT_FALSE(DeviceInfo::HasSubdir(temp_dir.path(),
530 FilePath("nonexistent")));
Thieu Le8f1c8352012-04-16 11:02:12 -0700531}
532
Paul Stewartca876ee2012-04-21 08:55:58 -0700533class DeviceInfoTechnologyTest : public DeviceInfoTest {
534 public:
Jason Glasgowabc54032012-04-20 16:08:32 -0400535 DeviceInfoTechnologyTest()
536 : DeviceInfoTest(),
537 test_device_name_(kTestDeviceName) {}
Paul Stewartca876ee2012-04-21 08:55:58 -0700538 virtual ~DeviceInfoTechnologyTest() {}
539
540 virtual void SetUp() {
541 temp_dir_.CreateUniqueTempDir();
542 device_info_root_ = temp_dir_.path().Append("sys/class/net");
543 device_info_.device_info_root_ = device_info_root_;
544 // Most tests require that the uevent file exist.
545 CreateInfoFile("uevent", "xxx");
546 }
547
548 Technology::Identifier GetDeviceTechnology() {
Jason Glasgowabc54032012-04-20 16:08:32 -0400549 return device_info_.GetDeviceTechnology(test_device_name_);
Paul Stewartca876ee2012-04-21 08:55:58 -0700550 }
551 FilePath GetInfoPath(const string &name);
552 void CreateInfoFile(const string &name, const string &contents);
553 void CreateInfoSymLink(const string &name, const string &contents);
Jason Glasgowabc54032012-04-20 16:08:32 -0400554 void SetDeviceName(const string &name) {
555 test_device_name_ = name;
556 SetUp();
557 }
Paul Stewartca876ee2012-04-21 08:55:58 -0700558
559 protected:
560 ScopedTempDir temp_dir_;
561 FilePath device_info_root_;
Jason Glasgowabc54032012-04-20 16:08:32 -0400562 string test_device_name_;
Paul Stewartca876ee2012-04-21 08:55:58 -0700563};
564
565FilePath DeviceInfoTechnologyTest::GetInfoPath(const string &name) {
Jason Glasgowabc54032012-04-20 16:08:32 -0400566 return device_info_root_.Append(test_device_name_).Append(name);
Paul Stewartca876ee2012-04-21 08:55:58 -0700567}
568
569void DeviceInfoTechnologyTest::CreateInfoFile(const string &name,
570 const string &contents) {
571 FilePath info_path = GetInfoPath(name);
572 EXPECT_TRUE(file_util::CreateDirectory(info_path.DirName()));
573 string contents_newline(contents + "\n");
574 EXPECT_TRUE(file_util::WriteFile(info_path, contents_newline.c_str(),
575 contents_newline.size()));
576}
577
578void DeviceInfoTechnologyTest::CreateInfoSymLink(const string &name,
579 const string &contents) {
580 FilePath info_path = GetInfoPath(name);
Paul Stewartca876ee2012-04-21 08:55:58 -0700581 EXPECT_TRUE(file_util::CreateDirectory(info_path.DirName()));
582 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath(contents), info_path));
583}
584
585TEST_F(DeviceInfoTechnologyTest, Unknown) {
586 EXPECT_EQ(Technology::kUnknown, GetDeviceTechnology());
587 // Should still be unknown even without a uevent file.
588 EXPECT_TRUE(file_util::Delete(GetInfoPath("uevent"), FALSE));
589 EXPECT_EQ(Technology::kUnknown, GetDeviceTechnology());
590}
591
592TEST_F(DeviceInfoTechnologyTest, Loopback) {
593 CreateInfoFile("type", base::IntToString(ARPHRD_LOOPBACK));
594 EXPECT_EQ(Technology::kLoopback, GetDeviceTechnology());
595}
596
597TEST_F(DeviceInfoTechnologyTest, PPP) {
598 CreateInfoFile("type", base::IntToString(ARPHRD_PPP));
599 EXPECT_EQ(Technology::kPPP, GetDeviceTechnology());
600}
601
602TEST_F(DeviceInfoTechnologyTest, Tunnel) {
603 CreateInfoFile("tun_flags", base::IntToString(IFF_TUN));
604 EXPECT_EQ(Technology::kTunnel, GetDeviceTechnology());
605}
606
607TEST_F(DeviceInfoTechnologyTest, WiFi) {
608 CreateInfoFile("uevent", "DEVTYPE=wlan");
609 EXPECT_EQ(Technology::kWifi, GetDeviceTechnology());
610 CreateInfoFile("uevent", "foo\nDEVTYPE=wlan");
611 EXPECT_EQ(Technology::kWifi, GetDeviceTechnology());
612 CreateInfoFile("type", base::IntToString(ARPHRD_IEEE80211_RADIOTAP));
613 EXPECT_EQ(Technology::kWiFiMonitor, GetDeviceTechnology());
614}
615
616TEST_F(DeviceInfoTechnologyTest, Ethernet) {
617 CreateInfoSymLink("device/driver", "xxx");
618 EXPECT_EQ(Technology::kEthernet, GetDeviceTechnology());
619}
620
Darin Petkove4b27022012-05-16 13:28:50 +0200621TEST_F(DeviceInfoTechnologyTest, WiMax) {
622 CreateInfoSymLink("device/driver", "gdm_wimax");
623 EXPECT_EQ(Technology::kWiMax, GetDeviceTechnology());
624}
625
Paul Stewartca876ee2012-04-21 08:55:58 -0700626TEST_F(DeviceInfoTechnologyTest, CellularGobi1) {
627 CreateInfoSymLink("device/driver", "blah/foo/gobi");
628 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
629}
630
631TEST_F(DeviceInfoTechnologyTest, CellularGobi2) {
632 CreateInfoSymLink("device/driver", "../GobiNet");
633 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
634}
635
636TEST_F(DeviceInfoTechnologyTest, QCUSB) {
637 CreateInfoSymLink("device/driver", "QCUSBNet2k");
638 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
639}
640
641// Modem with absolute driver path with top-level tty file:
642// /sys/class/net/dev0/device -> /sys/devices/virtual/0/00
643// /sys/devices/virtual/0/00/driver -> /drivers/cdc_ether
644// /sys/devices/virtual/0/01/tty [empty directory]
645TEST_F(DeviceInfoTechnologyTest, CDCEtherModem1) {
646 FilePath device_root(temp_dir_.path().Append("sys/devices/virtual/0"));
647 FilePath device_path(device_root.Append("00"));
648 EXPECT_TRUE(file_util::CreateDirectory(device_path));
649 CreateInfoSymLink("device", device_path.value());
650 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
651 device_path.Append("driver")));
652 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/tty")));
653 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
654}
655
656// Modem with relative driver path with top-level tty file.
657// /sys/class/net/dev0/device -> ../../../device_dir/0/00
658// /sys/device_dir/0/00/driver -> /drivers/cdc_ether
659// /sys/device_dir/0/01/tty [empty directory]
660TEST_F(DeviceInfoTechnologyTest, CDCEtherModem2) {
661 CreateInfoSymLink("device", "../../../device_dir/0/00");
662 FilePath device_root(temp_dir_.path().Append("sys/device_dir/0"));
663 FilePath device_path(device_root.Append("00"));
664 EXPECT_TRUE(file_util::CreateDirectory(device_path));
665 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
666 device_path.Append("driver")));
667 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/tty")));
668 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
669}
670
671// Modem with relative driver path with lower-level tty file.
672// /sys/class/net/dev0/device -> ../../../device_dir/0/00
673// /sys/device_dir/0/00/driver -> /drivers/cdc_ether
674// /sys/device_dir/0/01/yyy/tty [empty directory]
675TEST_F(DeviceInfoTechnologyTest, CDCEtherModem3) {
676 CreateInfoSymLink("device", "../../../device_dir/0/00");
677 FilePath device_root(temp_dir_.path().Append("sys/device_dir/0"));
678 FilePath device_path(device_root.Append("00"));
679 EXPECT_TRUE(file_util::CreateDirectory(device_path));
680 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
681 device_path.Append("driver")));
682 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/yyy/tty")));
683 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
684}
685
686TEST_F(DeviceInfoTechnologyTest, CDCEtherNonModem) {
687 CreateInfoSymLink("device", "device_dir");
688 CreateInfoSymLink("device_dir/driver", "cdc_ether");
689 EXPECT_EQ(Technology::kEthernet, GetDeviceTechnology());
690}
691
Jason Glasgowabc54032012-04-20 16:08:32 -0400692TEST_F(DeviceInfoTechnologyTest, PseudoModem) {
693 SetDeviceName("pseudomodem");
694 CreateInfoSymLink("device", "device_dir");
695 CreateInfoSymLink("device_dir/driver", "cdc_ether");
696 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
697
698 SetDeviceName("pseudomodem9");
699 CreateInfoSymLink("device", "device_dir");
700 CreateInfoSymLink("device_dir/driver", "cdc_ether");
701 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
702}
703
Chris Masone9be4a9d2011-05-16 15:44:09 -0700704} // namespace shill