blob: 43d267a453e99092b24689ab84ca488fa2267678 [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"
Chris Masone9be4a9d2011-05-16 15:44:09 -070038
Eric Shienbrood3e20a232012-02-16 11:35:56 -050039using base::Callback;
Darin Petkove6193c02011-08-11 12:42:40 -070040using std::map;
Darin Petkov633ac6f2011-07-08 13:56:13 -070041using std::string;
Paul Stewart9a908082011-08-31 12:18:48 -070042using std::vector;
Darin Petkov633ac6f2011-07-08 13:56:13 -070043using testing::_;
Paul Stewart8c116a92012-05-02 18:30:03 -070044using testing::Mock;
Darin Petkov633ac6f2011-07-08 13:56:13 -070045using testing::Return;
Paul Stewart9a908082011-08-31 12:18:48 -070046using testing::StrictMock;
Darin Petkov633ac6f2011-07-08 13:56:13 -070047using testing::Test;
48
Chris Masone9be4a9d2011-05-16 15:44:09 -070049namespace shill {
Darin Petkov633ac6f2011-07-08 13:56:13 -070050
51class TestEventDispatcher : public EventDispatcher {
52 public:
Paul Stewart26b327e2011-10-19 11:38:09 -070053 virtual IOHandler *CreateInputHandler(
mukesh agrawal1830fa12011-09-26 14:31:40 -070054 int /*fd*/,
Eric Shienbrood3e20a232012-02-16 11:35:56 -050055 const Callback<void(InputData*)> &/*callback*/) {
Darin Petkov633ac6f2011-07-08 13:56:13 -070056 return NULL;
57 }
58};
Chris Masone9be4a9d2011-05-16 15:44:09 -070059
60class DeviceInfoTest : public Test {
61 public:
62 DeviceInfoTest()
Thieu Le3426c8f2012-01-11 17:35:11 -080063 : manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
64 device_info_(&control_interface_, &dispatcher_, &metrics_, &manager_) {
Chris Masone9be4a9d2011-05-16 15:44:09 -070065 }
Paul Stewartca876ee2012-04-21 08:55:58 -070066 virtual ~DeviceInfoTest() {}
Darin Petkov633ac6f2011-07-08 13:56:13 -070067
Paul Stewart9a908082011-08-31 12:18:48 -070068 virtual void SetUp() {
69 device_info_.rtnl_handler_ = &rtnl_handler_;
Paul Stewart8c116a92012-05-02 18:30:03 -070070 device_info_.routing_table_ = &routing_table_;
Paul Stewart9a908082011-08-31 12:18:48 -070071 }
72
Paul Stewart8c116a92012-05-02 18:30:03 -070073 IPAddress CreateInterfaceAddress() {
74 // Create an IP address entry (as if left-over from a previous connection
75 // manager).
76 IPAddress address(IPAddress::kFamilyIPv4);
77 EXPECT_TRUE(address.SetAddressFromString(kTestIPAddress0));
78 address.set_prefix(kTestIPAddressPrefix0);
79 vector<DeviceInfo::AddressData> &addresses =
80 device_info_.infos_[kTestDeviceIndex].ip_addresses;
81 addresses.push_back(DeviceInfo::AddressData(address, 0, RT_SCOPE_UNIVERSE));
82 EXPECT_EQ(1, addresses.size());
83 return address;
84 }
85
86 DeviceRefPtr CreateDevice(const std::string &link_name,
87 const std::string &address,
88 int interface_index,
89 Technology::Identifier technology) {
90 return device_info_.CreateDevice(link_name, address, interface_index,
91 technology);
92 }
93
94
Paul Stewarta3c56f92011-05-26 07:08:52 -070095 protected:
Chris Masoneb2e326b2011-07-12 13:28:51 -070096 static const int kTestDeviceIndex;
Darin Petkov633ac6f2011-07-08 13:56:13 -070097 static const char kTestDeviceName[];
Paul Stewart9a908082011-08-31 12:18:48 -070098 static const char kTestMACAddress[];
99 static const char kTestIPAddress0[];
100 static const int kTestIPAddressPrefix0;
101 static const char kTestIPAddress1[];
102 static const int kTestIPAddressPrefix1;
103 static const char kTestIPAddress2[];
104 static const char kTestIPAddress3[];
105 static const char kTestIPAddress4[];
Darin Petkov633ac6f2011-07-08 13:56:13 -0700106
Paul Stewart9a908082011-08-31 12:18:48 -0700107 RTNLMessage *BuildLinkMessage(RTNLMessage::Mode mode);
Paul Stewarte81eb702012-04-11 15:04:53 -0700108 RTNLMessage *BuildLinkMessageWithInterfaceName(RTNLMessage::Mode mode,
109 const string &interface_name);
Paul Stewart9a908082011-08-31 12:18:48 -0700110 RTNLMessage *BuildAddressMessage(RTNLMessage::Mode mode,
111 const IPAddress &address,
112 unsigned char flags,
113 unsigned char scope);
Chris Masone2aa97072011-08-09 17:35:08 -0700114 void SendMessageToDeviceInfo(const RTNLMessage &message);
Darin Petkov633ac6f2011-07-08 13:56:13 -0700115
Darin Petkovafa6fc42011-06-21 16:21:08 -0700116 MockGLib glib_;
Chris Masone46eaaf52011-05-24 13:08:30 -0700117 MockControl control_interface_;
Thieu Le3426c8f2012-01-11 17:35:11 -0800118 MockMetrics metrics_;
Paul Stewart9a908082011-08-31 12:18:48 -0700119 StrictMock<MockManager> manager_;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700120 DeviceInfo device_info_;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700121 TestEventDispatcher dispatcher_;
Paul Stewart8c116a92012-05-02 18:30:03 -0700122 MockRoutingTable routing_table_;
Paul Stewart9a908082011-08-31 12:18:48 -0700123 StrictMock<MockRTNLHandler> rtnl_handler_;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700124};
125
Chris Masoneb2e326b2011-07-12 13:28:51 -0700126const int DeviceInfoTest::kTestDeviceIndex = 123456;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700127const char DeviceInfoTest::kTestDeviceName[] = "test-device";
Paul Stewart9a908082011-08-31 12:18:48 -0700128const char DeviceInfoTest::kTestMACAddress[] = {
Darin Petkove3e1cfa2011-08-11 13:41:17 -0700129 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
Paul Stewart9a908082011-08-31 12:18:48 -0700130const char DeviceInfoTest::kTestIPAddress0[] = "192.168.1.1";
131const int DeviceInfoTest::kTestIPAddressPrefix0 = 24;
132const char DeviceInfoTest::kTestIPAddress1[] = "fe80::1aa9:5ff:abcd:1234";
133const int DeviceInfoTest::kTestIPAddressPrefix1 = 64;
134const char DeviceInfoTest::kTestIPAddress2[] = "fe80::1aa9:5ff:abcd:1235";
135const char DeviceInfoTest::kTestIPAddress3[] = "fe80::1aa9:5ff:abcd:1236";
136const char DeviceInfoTest::kTestIPAddress4[] = "fe80::1aa9:5ff:abcd:1237";
Chris Masone9be4a9d2011-05-16 15:44:09 -0700137
Paul Stewarte81eb702012-04-11 15:04:53 -0700138RTNLMessage *DeviceInfoTest::BuildLinkMessageWithInterfaceName(
139 RTNLMessage::Mode mode, const string &interface_name) {
Paul Stewart9a908082011-08-31 12:18:48 -0700140 RTNLMessage *message = new RTNLMessage(
141 RTNLMessage::kTypeLink,
142 mode,
143 0,
144 0,
145 0,
146 kTestDeviceIndex,
Paul Stewart7355ce12011-09-02 10:47:01 -0700147 IPAddress::kFamilyIPv4);
Chris Masone2aa97072011-08-09 17:35:08 -0700148 message->SetAttribute(static_cast<uint16>(IFLA_IFNAME),
Paul Stewarte81eb702012-04-11 15:04:53 -0700149 ByteString(interface_name, true));
Paul Stewart9a908082011-08-31 12:18:48 -0700150 ByteString test_address(kTestMACAddress, sizeof(kTestMACAddress));
Chris Masone626719f2011-08-18 16:58:48 -0700151 message->SetAttribute(IFLA_ADDRESS, test_address);
Chris Masone2aa97072011-08-09 17:35:08 -0700152 return message;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700153}
154
Paul Stewarte81eb702012-04-11 15:04:53 -0700155RTNLMessage *DeviceInfoTest::BuildLinkMessage(RTNLMessage::Mode mode) {
156 return BuildLinkMessageWithInterfaceName(mode, kTestDeviceName);
157}
158
Paul Stewart9a908082011-08-31 12:18:48 -0700159RTNLMessage *DeviceInfoTest::BuildAddressMessage(RTNLMessage::Mode mode,
160 const IPAddress &address,
161 unsigned char flags,
162 unsigned char scope) {
163 RTNLMessage *message = new RTNLMessage(
164 RTNLMessage::kTypeAddress,
165 mode,
166 0,
167 0,
168 0,
169 kTestDeviceIndex,
170 address.family());
171 message->SetAttribute(IFA_ADDRESS, address.address());
172 message->set_address_status(
173 RTNLMessage::AddressStatus(address.prefix(), flags, scope));
174 return message;
175}
176
Chris Masone2aa97072011-08-09 17:35:08 -0700177void DeviceInfoTest::SendMessageToDeviceInfo(const RTNLMessage &message) {
Paul Stewart9a908082011-08-31 12:18:48 -0700178 if (message.type() == RTNLMessage::kTypeLink) {
179 device_info_.LinkMsgHandler(message);
180 } else if (message.type() == RTNLMessage::kTypeAddress) {
181 device_info_.AddressMsgHandler(message);
182 } else {
183 NOTREACHED();
184 }
185}
186
187MATCHER_P(IsIPAddress, address, "") {
188 // NB: IPAddress objects don't support the "==" operator as per style, so
189 // we need a custom matcher.
190 return address.Equals(arg);
Darin Petkov633ac6f2011-07-08 13:56:13 -0700191}
192
Paul Stewart8c116a92012-05-02 18:30:03 -0700193TEST_F(DeviceInfoTest, StartStop) {
194 EXPECT_FALSE(device_info_.link_listener_.get());
195 EXPECT_FALSE(device_info_.address_listener_.get());
196 EXPECT_TRUE(device_info_.infos_.empty());
197
198 EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestLink |
199 RTNLHandler::kRequestAddr));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700200 device_info_.Start();
Paul Stewart8c116a92012-05-02 18:30:03 -0700201 EXPECT_TRUE(device_info_.link_listener_.get());
202 EXPECT_TRUE(device_info_.address_listener_.get());
203 EXPECT_TRUE(device_info_.infos_.empty());
204 Mock::VerifyAndClearExpectations(&rtnl_handler_);
205
206 CreateInterfaceAddress();
207 EXPECT_FALSE(device_info_.infos_.empty());
208
209 device_info_.Stop();
210 EXPECT_FALSE(device_info_.link_listener_.get());
211 EXPECT_FALSE(device_info_.address_listener_.get());
212 EXPECT_TRUE(device_info_.infos_.empty());
213}
214
215TEST_F(DeviceInfoTest, DeviceEnumeration) {
Paul Stewart9a908082011-08-31 12:18:48 -0700216 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
Darin Petkove6193c02011-08-11 12:42:40 -0700217 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_LOWER_UP, 0));
218 EXPECT_FALSE(device_info_.GetDevice(kTestDeviceIndex).get());
Darin Petkovf8046b82012-04-24 16:29:23 +0200219 EXPECT_EQ(-1, device_info_.GetIndex(kTestDeviceName));
Darin Petkove6193c02011-08-11 12:42:40 -0700220 SendMessageToDeviceInfo(*message);
221 EXPECT_TRUE(device_info_.GetDevice(kTestDeviceIndex).get());
222 unsigned int flags = 0;
223 EXPECT_TRUE(device_info_.GetFlags(kTestDeviceIndex, &flags));
224 EXPECT_EQ(IFF_LOWER_UP, flags);
Darin Petkove3e1cfa2011-08-11 13:41:17 -0700225 ByteString address;
Paul Stewart32852962011-08-30 14:06:53 -0700226 EXPECT_TRUE(device_info_.GetMACAddress(kTestDeviceIndex, &address));
Darin Petkove3e1cfa2011-08-11 13:41:17 -0700227 EXPECT_FALSE(address.IsEmpty());
Paul Stewart9a908082011-08-31 12:18:48 -0700228 EXPECT_TRUE(address.Equals(ByteString(kTestMACAddress,
229 sizeof(kTestMACAddress))));
Darin Petkovf8046b82012-04-24 16:29:23 +0200230 EXPECT_EQ(kTestDeviceIndex, device_info_.GetIndex(kTestDeviceName));
Paul Stewarta3c56f92011-05-26 07:08:52 -0700231
Paul Stewart9a908082011-08-31 12:18:48 -0700232 message.reset(BuildLinkMessage(RTNLMessage::kModeAdd));
Darin Petkove6193c02011-08-11 12:42:40 -0700233 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_UP | IFF_RUNNING, 0));
234 SendMessageToDeviceInfo(*message);
235 EXPECT_TRUE(device_info_.GetFlags(kTestDeviceIndex, &flags));
236 EXPECT_EQ(IFF_UP | IFF_RUNNING, flags);
Paul Stewartb50f0b92011-05-16 16:31:42 -0700237
Paul Stewart9a908082011-08-31 12:18:48 -0700238 message.reset(BuildLinkMessage(RTNLMessage::kModeDelete));
Paul Stewart8c116a92012-05-02 18:30:03 -0700239 EXPECT_CALL(manager_, DeregisterDevice(_)).Times(1);
Darin Petkove6193c02011-08-11 12:42:40 -0700240 SendMessageToDeviceInfo(*message);
241 EXPECT_FALSE(device_info_.GetDevice(kTestDeviceIndex).get());
242 EXPECT_FALSE(device_info_.GetFlags(kTestDeviceIndex, NULL));
Darin Petkovf8046b82012-04-24 16:29:23 +0200243 EXPECT_EQ(-1, device_info_.GetIndex(kTestDeviceName));
Paul Stewart8c116a92012-05-02 18:30:03 -0700244}
Paul Stewarta3c56f92011-05-26 07:08:52 -0700245
Paul Stewart8c116a92012-05-02 18:30:03 -0700246TEST_F(DeviceInfoTest, CreateDeviceCellular) {
247 IPAddress address = CreateInterfaceAddress();
248
249 // A cellular device should be offered to ModemInfo.
250 StrictMock<MockModemInfo> modem_info;
251 EXPECT_CALL(manager_, modem_info()).WillOnce(Return(&modem_info));
252 EXPECT_CALL(modem_info, OnDeviceInfoAvailable(kTestDeviceName)).Times(1);
253 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
254 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
255 IsIPAddress(address)));
256 EXPECT_FALSE(CreateDevice(
257 kTestDeviceName, "address", kTestDeviceIndex, Technology::kCellular));
258}
259
Darin Petkove4b27022012-05-16 13:28:50 +0200260TEST_F(DeviceInfoTest, CreateDeviceWiMax) {
261 IPAddress address = CreateInterfaceAddress();
262
263 // A WiMax device should be offered to WiMaxProvider.
264 StrictMock<MockWiMaxProvider> wimax_provider;
265 EXPECT_CALL(manager_, wimax_provider()).WillOnce(Return(&wimax_provider));
266 EXPECT_CALL(wimax_provider, OnDeviceInfoAvailable(kTestDeviceName)).Times(1);
267 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
268 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
269 IsIPAddress(address)));
270 EXPECT_FALSE(CreateDevice(
271 kTestDeviceName, "address", kTestDeviceIndex, Technology::kWiMax));
272}
273
Paul Stewart8c116a92012-05-02 18:30:03 -0700274TEST_F(DeviceInfoTest, CreateDeviceEthernet) {
275 IPAddress address = CreateInterfaceAddress();
276
277 // An Ethernet device should cause routes and addresses to be flushed.
278 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
279 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
280 IsIPAddress(address)));
281 DeviceRefPtr device = CreateDevice(
282 kTestDeviceName, "address", kTestDeviceIndex, Technology::kEthernet);
283 EXPECT_TRUE(device);
284 Mock::VerifyAndClearExpectations(&routing_table_);
285 Mock::VerifyAndClearExpectations(&rtnl_handler_);
286
287 // The Ethernet device destructor notifies the manager.
288 EXPECT_CALL(manager_, UpdateEnabledTechnologies()).Times(1);
289 device = NULL;
290}
291
292TEST_F(DeviceInfoTest, CreateDeviceVirtioEthernet) {
293 IPAddress address = CreateInterfaceAddress();
294
295 // VirtioEthernet is identical to Ethernet from the perspective of this test.
296 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
297 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
298 IsIPAddress(address)));
299 DeviceRefPtr device = CreateDevice(
300 kTestDeviceName, "address", kTestDeviceIndex,
301 Technology::kVirtioEthernet);
302 EXPECT_TRUE(device);
303 Mock::VerifyAndClearExpectations(&routing_table_);
304 Mock::VerifyAndClearExpectations(&rtnl_handler_);
305
306 // The Ethernet device destructor notifies the manager.
307 EXPECT_CALL(manager_, UpdateEnabledTechnologies()).Times(1);
308 device = NULL;
309}
310
311TEST_F(DeviceInfoTest, CreateDeviceWiFi) {
312 IPAddress address = CreateInterfaceAddress();
313
314 // WiFi looks a lot like Ethernet too.
315 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
316 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
317 IsIPAddress(address)));
318 EXPECT_TRUE(CreateDevice(
319 kTestDeviceName, "address", kTestDeviceIndex, Technology::kWifi));
320}
321
322TEST_F(DeviceInfoTest, CreateDeviceTunnelAccepted) {
323 IPAddress address = CreateInterfaceAddress();
324
325 // A VPN device should be offered to VPNProvider.
326 StrictMock<MockVPNProvider> vpn_provider;
327 EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&vpn_provider));
328 EXPECT_CALL(vpn_provider,
329 OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
330 .WillOnce(Return(true));
331 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
332 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
333 IsIPAddress(address)));
334 EXPECT_CALL(rtnl_handler_, RemoveInterface(_)).Times(0);
335 EXPECT_FALSE(CreateDevice(
336 kTestDeviceName, "address", kTestDeviceIndex, Technology::kTunnel));
337}
338
339TEST_F(DeviceInfoTest, CreateDeviceTunnelRejected) {
340 IPAddress address = CreateInterfaceAddress();
341
342 // A VPN device should be offered to VPNProvider.
343 StrictMock<MockVPNProvider> vpn_provider;
344 EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&vpn_provider));
345 EXPECT_CALL(vpn_provider,
346 OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
347 .WillOnce(Return(false));
348 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
349 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
350 IsIPAddress(address)));
351 // Since the device was rejected by the VPNProvider, DeviceInfo will
352 // remove the interface.
353 EXPECT_CALL(rtnl_handler_, RemoveInterface(kTestDeviceIndex)).Times(1);
354 EXPECT_FALSE(CreateDevice(
355 kTestDeviceName, "address", kTestDeviceIndex, Technology::kTunnel));
356}
357
358TEST_F(DeviceInfoTest, CreateDevicePPP) {
359 IPAddress address = CreateInterfaceAddress();
360
361 // A VPN device should be offered to VPNProvider.
362 StrictMock<MockVPNProvider> vpn_provider;
363 EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&vpn_provider));
364 EXPECT_CALL(vpn_provider,
365 OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
366 .WillOnce(Return(false));
367 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
368 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
369 IsIPAddress(address)));
370 // We do not remove PPP interfaces even if the provider does not accept it.
371 EXPECT_CALL(rtnl_handler_, RemoveInterface(_)).Times(0);
372 EXPECT_FALSE(CreateDevice(
373 kTestDeviceName, "address", kTestDeviceIndex, Technology::kPPP));
374}
375
376TEST_F(DeviceInfoTest, CreateDeviceLoopback) {
377 // A loopback device should be brought up, and nothing else done to it.
378 EXPECT_CALL(routing_table_, FlushRoutes(_)).Times(0);
379 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(_, _)).Times(0);
380 EXPECT_CALL(rtnl_handler_,
381 SetInterfaceFlags(kTestDeviceIndex, IFF_UP, IFF_UP)).Times(1);
382 EXPECT_FALSE(CreateDevice(
383 kTestDeviceName, "address", kTestDeviceIndex, Technology::kLoopback));
384}
385
386TEST_F(DeviceInfoTest, CreateDeviceUnknown) {
387 IPAddress address = CreateInterfaceAddress();
388
389 // An unknown (blacklisted, unhandled, etc) device won't be flushed or
390 // registered.
391 EXPECT_CALL(routing_table_, FlushRoutes(_)).Times(0);
392 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(_, _)).Times(0);
393 EXPECT_TRUE(CreateDevice(
394 kTestDeviceName, "address", kTestDeviceIndex, Technology::kUnknown));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700395}
396
mukesh agrawal8f317b62011-07-15 11:53:23 -0700397TEST_F(DeviceInfoTest, DeviceBlackList) {
398 device_info_.AddDeviceToBlackList(kTestDeviceName);
Paul Stewart9a908082011-08-31 12:18:48 -0700399 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
Darin Petkove6193c02011-08-11 12:42:40 -0700400 SendMessageToDeviceInfo(*message);
mukesh agrawal8f317b62011-07-15 11:53:23 -0700401
Darin Petkove6193c02011-08-11 12:42:40 -0700402 DeviceRefPtr device = device_info_.GetDevice(kTestDeviceIndex);
403 ASSERT_TRUE(device.get());
Paul Stewartfdd16072011-09-16 12:41:35 -0700404 EXPECT_TRUE(device->TechnologyIs(Technology::kBlacklisted));
mukesh agrawal8f317b62011-07-15 11:53:23 -0700405}
406
Paul Stewart9a908082011-08-31 12:18:48 -0700407TEST_F(DeviceInfoTest, DeviceAddressList) {
Paul Stewart9a908082011-08-31 12:18:48 -0700408 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
409 SendMessageToDeviceInfo(*message);
410
411 vector<DeviceInfo::AddressData> addresses;
412 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
413 EXPECT_TRUE(addresses.empty());
414
415 // Add an address to the device address list
Paul Stewart7355ce12011-09-02 10:47:01 -0700416 IPAddress ip_address0(IPAddress::kFamilyIPv4);
Paul Stewart9a908082011-08-31 12:18:48 -0700417 EXPECT_TRUE(ip_address0.SetAddressFromString(kTestIPAddress0));
418 ip_address0.set_prefix(kTestIPAddressPrefix0);
419 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address0, 0, 0));
420 SendMessageToDeviceInfo(*message);
421 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
422 EXPECT_EQ(1, addresses.size());
423 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
424
425 // Re-adding the same address shouldn't cause the address list to change
426 SendMessageToDeviceInfo(*message);
427 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
428 EXPECT_EQ(1, addresses.size());
429 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
430
431 // Adding a new address should expand the list
Paul Stewart7355ce12011-09-02 10:47:01 -0700432 IPAddress ip_address1(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700433 EXPECT_TRUE(ip_address1.SetAddressFromString(kTestIPAddress1));
434 ip_address1.set_prefix(kTestIPAddressPrefix1);
435 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address1, 0, 0));
436 SendMessageToDeviceInfo(*message);
437 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
438 EXPECT_EQ(2, addresses.size());
439 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
440 EXPECT_TRUE(ip_address1.Equals(addresses[1].address));
441
442 // Deleting an address should reduce the list
443 message.reset(BuildAddressMessage(RTNLMessage::kModeDelete,
444 ip_address0,
445 0,
446 0));
447 SendMessageToDeviceInfo(*message);
448 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
449 EXPECT_EQ(1, addresses.size());
450 EXPECT_TRUE(ip_address1.Equals(addresses[0].address));
451
452 // Delete last item
453 message.reset(BuildAddressMessage(RTNLMessage::kModeDelete,
454 ip_address1,
455 0,
456 0));
457 SendMessageToDeviceInfo(*message);
458 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
459 EXPECT_TRUE(addresses.empty());
460
461 // Delete device
462 message.reset(BuildLinkMessage(RTNLMessage::kModeDelete));
Paul Stewart8c116a92012-05-02 18:30:03 -0700463 EXPECT_CALL(manager_, DeregisterDevice(_)).Times(1);
Paul Stewart9a908082011-08-31 12:18:48 -0700464 SendMessageToDeviceInfo(*message);
465
466 // Should be able to handle message for interface that doesn't exist
467 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address0, 0, 0));
468 SendMessageToDeviceInfo(*message);
469 EXPECT_FALSE(device_info_.GetDevice(kTestDeviceIndex).get());
Paul Stewart9a908082011-08-31 12:18:48 -0700470}
471
472TEST_F(DeviceInfoTest, FlushAddressList) {
Paul Stewart9a908082011-08-31 12:18:48 -0700473 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
474 SendMessageToDeviceInfo(*message);
475
Paul Stewart7355ce12011-09-02 10:47:01 -0700476 IPAddress address1(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700477 EXPECT_TRUE(address1.SetAddressFromString(kTestIPAddress1));
478 address1.set_prefix(kTestIPAddressPrefix1);
479 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
480 address1,
481 0,
482 RT_SCOPE_UNIVERSE));
483 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700484 IPAddress address2(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700485 EXPECT_TRUE(address2.SetAddressFromString(kTestIPAddress2));
486 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
487 address2,
488 IFA_F_TEMPORARY,
489 RT_SCOPE_UNIVERSE));
490 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700491 IPAddress address3(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700492 EXPECT_TRUE(address3.SetAddressFromString(kTestIPAddress3));
493 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
494 address3,
495 0,
496 RT_SCOPE_LINK));
497 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700498 IPAddress address4(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700499 EXPECT_TRUE(address4.SetAddressFromString(kTestIPAddress4));
500 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
501 address4,
502 IFA_F_PERMANENT,
503 RT_SCOPE_UNIVERSE));
504 SendMessageToDeviceInfo(*message);
505
506 // DeviceInfo now has 4 addresses associated with it, but only two of
507 // them are valid for flush.
508 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
509 IsIPAddress(address1)));
510 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
511 IsIPAddress(address2)));
512 device_info_.FlushAddresses(kTestDeviceIndex);
Paul Stewart9a908082011-08-31 12:18:48 -0700513}
514
Thieu Leb27beee2012-04-20 09:19:06 -0700515TEST_F(DeviceInfoTest, HasSubdir) {
Thieu Le8f1c8352012-04-16 11:02:12 -0700516 ScopedTempDir temp_dir;
517 EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
Thieu Leb27beee2012-04-20 09:19:06 -0700518 EXPECT_TRUE(file_util::CreateDirectory(temp_dir.path().Append("child1")));
519 FilePath child2 = temp_dir.path().Append("child2");
520 EXPECT_TRUE(file_util::CreateDirectory(child2));
521 FilePath grandchild = child2.Append("grandchild");
Thieu Le8f1c8352012-04-16 11:02:12 -0700522 EXPECT_TRUE(file_util::CreateDirectory(grandchild));
523 EXPECT_TRUE(file_util::CreateDirectory(grandchild.Append("greatgrandchild")));
Thieu Leb27beee2012-04-20 09:19:06 -0700524 EXPECT_TRUE(DeviceInfo::HasSubdir(temp_dir.path(),
525 FilePath("grandchild")));
526 EXPECT_TRUE(DeviceInfo::HasSubdir(temp_dir.path(),
527 FilePath("greatgrandchild")));
528 EXPECT_FALSE(DeviceInfo::HasSubdir(temp_dir.path(),
529 FilePath("nonexistent")));
Thieu Le8f1c8352012-04-16 11:02:12 -0700530}
531
Paul Stewartca876ee2012-04-21 08:55:58 -0700532class DeviceInfoTechnologyTest : public DeviceInfoTest {
533 public:
Jason Glasgowabc54032012-04-20 16:08:32 -0400534 DeviceInfoTechnologyTest()
535 : DeviceInfoTest(),
536 test_device_name_(kTestDeviceName) {}
Paul Stewartca876ee2012-04-21 08:55:58 -0700537 virtual ~DeviceInfoTechnologyTest() {}
538
539 virtual void SetUp() {
540 temp_dir_.CreateUniqueTempDir();
541 device_info_root_ = temp_dir_.path().Append("sys/class/net");
542 device_info_.device_info_root_ = device_info_root_;
543 // Most tests require that the uevent file exist.
544 CreateInfoFile("uevent", "xxx");
545 }
546
547 Technology::Identifier GetDeviceTechnology() {
Jason Glasgowabc54032012-04-20 16:08:32 -0400548 return device_info_.GetDeviceTechnology(test_device_name_);
Paul Stewartca876ee2012-04-21 08:55:58 -0700549 }
550 FilePath GetInfoPath(const string &name);
551 void CreateInfoFile(const string &name, const string &contents);
552 void CreateInfoSymLink(const string &name, const string &contents);
Jason Glasgowabc54032012-04-20 16:08:32 -0400553 void SetDeviceName(const string &name) {
554 test_device_name_ = name;
555 SetUp();
556 }
Paul Stewartca876ee2012-04-21 08:55:58 -0700557
558 protected:
559 ScopedTempDir temp_dir_;
560 FilePath device_info_root_;
Jason Glasgowabc54032012-04-20 16:08:32 -0400561 string test_device_name_;
Paul Stewartca876ee2012-04-21 08:55:58 -0700562};
563
564FilePath DeviceInfoTechnologyTest::GetInfoPath(const string &name) {
Jason Glasgowabc54032012-04-20 16:08:32 -0400565 return device_info_root_.Append(test_device_name_).Append(name);
Paul Stewartca876ee2012-04-21 08:55:58 -0700566}
567
568void DeviceInfoTechnologyTest::CreateInfoFile(const string &name,
569 const string &contents) {
570 FilePath info_path = GetInfoPath(name);
571 EXPECT_TRUE(file_util::CreateDirectory(info_path.DirName()));
572 string contents_newline(contents + "\n");
573 EXPECT_TRUE(file_util::WriteFile(info_path, contents_newline.c_str(),
574 contents_newline.size()));
575}
576
577void DeviceInfoTechnologyTest::CreateInfoSymLink(const string &name,
578 const string &contents) {
579 FilePath info_path = GetInfoPath(name);
Paul Stewartca876ee2012-04-21 08:55:58 -0700580 EXPECT_TRUE(file_util::CreateDirectory(info_path.DirName()));
581 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath(contents), info_path));
582}
583
584TEST_F(DeviceInfoTechnologyTest, Unknown) {
585 EXPECT_EQ(Technology::kUnknown, GetDeviceTechnology());
586 // Should still be unknown even without a uevent file.
587 EXPECT_TRUE(file_util::Delete(GetInfoPath("uevent"), FALSE));
588 EXPECT_EQ(Technology::kUnknown, GetDeviceTechnology());
589}
590
591TEST_F(DeviceInfoTechnologyTest, Loopback) {
592 CreateInfoFile("type", base::IntToString(ARPHRD_LOOPBACK));
593 EXPECT_EQ(Technology::kLoopback, GetDeviceTechnology());
594}
595
596TEST_F(DeviceInfoTechnologyTest, PPP) {
597 CreateInfoFile("type", base::IntToString(ARPHRD_PPP));
598 EXPECT_EQ(Technology::kPPP, GetDeviceTechnology());
599}
600
601TEST_F(DeviceInfoTechnologyTest, Tunnel) {
602 CreateInfoFile("tun_flags", base::IntToString(IFF_TUN));
603 EXPECT_EQ(Technology::kTunnel, GetDeviceTechnology());
604}
605
606TEST_F(DeviceInfoTechnologyTest, WiFi) {
607 CreateInfoFile("uevent", "DEVTYPE=wlan");
608 EXPECT_EQ(Technology::kWifi, GetDeviceTechnology());
609 CreateInfoFile("uevent", "foo\nDEVTYPE=wlan");
610 EXPECT_EQ(Technology::kWifi, GetDeviceTechnology());
611 CreateInfoFile("type", base::IntToString(ARPHRD_IEEE80211_RADIOTAP));
612 EXPECT_EQ(Technology::kWiFiMonitor, GetDeviceTechnology());
613}
614
615TEST_F(DeviceInfoTechnologyTest, Ethernet) {
616 CreateInfoSymLink("device/driver", "xxx");
617 EXPECT_EQ(Technology::kEthernet, GetDeviceTechnology());
618}
619
Darin Petkove4b27022012-05-16 13:28:50 +0200620TEST_F(DeviceInfoTechnologyTest, WiMax) {
621 CreateInfoSymLink("device/driver", "gdm_wimax");
622 EXPECT_EQ(Technology::kWiMax, GetDeviceTechnology());
623}
624
Paul Stewartca876ee2012-04-21 08:55:58 -0700625TEST_F(DeviceInfoTechnologyTest, CellularGobi1) {
626 CreateInfoSymLink("device/driver", "blah/foo/gobi");
627 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
628}
629
630TEST_F(DeviceInfoTechnologyTest, CellularGobi2) {
631 CreateInfoSymLink("device/driver", "../GobiNet");
632 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
633}
634
635TEST_F(DeviceInfoTechnologyTest, QCUSB) {
636 CreateInfoSymLink("device/driver", "QCUSBNet2k");
637 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
638}
639
640// Modem with absolute driver path with top-level tty file:
641// /sys/class/net/dev0/device -> /sys/devices/virtual/0/00
642// /sys/devices/virtual/0/00/driver -> /drivers/cdc_ether
643// /sys/devices/virtual/0/01/tty [empty directory]
644TEST_F(DeviceInfoTechnologyTest, CDCEtherModem1) {
645 FilePath device_root(temp_dir_.path().Append("sys/devices/virtual/0"));
646 FilePath device_path(device_root.Append("00"));
647 EXPECT_TRUE(file_util::CreateDirectory(device_path));
648 CreateInfoSymLink("device", device_path.value());
649 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
650 device_path.Append("driver")));
651 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/tty")));
652 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
653}
654
655// Modem with relative driver path with top-level tty file.
656// /sys/class/net/dev0/device -> ../../../device_dir/0/00
657// /sys/device_dir/0/00/driver -> /drivers/cdc_ether
658// /sys/device_dir/0/01/tty [empty directory]
659TEST_F(DeviceInfoTechnologyTest, CDCEtherModem2) {
660 CreateInfoSymLink("device", "../../../device_dir/0/00");
661 FilePath device_root(temp_dir_.path().Append("sys/device_dir/0"));
662 FilePath device_path(device_root.Append("00"));
663 EXPECT_TRUE(file_util::CreateDirectory(device_path));
664 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
665 device_path.Append("driver")));
666 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/tty")));
667 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
668}
669
670// Modem with relative driver path with lower-level tty file.
671// /sys/class/net/dev0/device -> ../../../device_dir/0/00
672// /sys/device_dir/0/00/driver -> /drivers/cdc_ether
673// /sys/device_dir/0/01/yyy/tty [empty directory]
674TEST_F(DeviceInfoTechnologyTest, CDCEtherModem3) {
675 CreateInfoSymLink("device", "../../../device_dir/0/00");
676 FilePath device_root(temp_dir_.path().Append("sys/device_dir/0"));
677 FilePath device_path(device_root.Append("00"));
678 EXPECT_TRUE(file_util::CreateDirectory(device_path));
679 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
680 device_path.Append("driver")));
681 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/yyy/tty")));
682 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
683}
684
685TEST_F(DeviceInfoTechnologyTest, CDCEtherNonModem) {
686 CreateInfoSymLink("device", "device_dir");
687 CreateInfoSymLink("device_dir/driver", "cdc_ether");
688 EXPECT_EQ(Technology::kEthernet, GetDeviceTechnology());
689}
690
Jason Glasgowabc54032012-04-20 16:08:32 -0400691TEST_F(DeviceInfoTechnologyTest, PseudoModem) {
692 SetDeviceName("pseudomodem");
693 CreateInfoSymLink("device", "device_dir");
694 CreateInfoSymLink("device_dir/driver", "cdc_ether");
695 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
696
697 SetDeviceName("pseudomodem9");
698 CreateInfoSymLink("device", "device_dir");
699 CreateInfoSymLink("device_dir/driver", "cdc_ether");
700 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
701}
702
Chris Masone9be4a9d2011-05-16 15:44:09 -0700703} // namespace shill