blob: 48a336e7f5874477b7c779bc6ea69b5fbce17707 [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>
Gary Morain41780232012-07-31 15:08:31 -070013#include <linux/sockios.h>
Paul Stewartca876ee2012-04-21 08:55:58 -070014#include <net/if_arp.h>
Chris Masone9be4a9d2011-05-16 15:44:09 -070015
Thieu Le8f1c8352012-04-16 11:02:12 -070016#include <base/file_util.h>
Chris Masone9be4a9d2011-05-16 15:44:09 -070017#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"
Christopher Wileyb691efd2012-08-09 13:51:51 -070026#include "shill/logging.h"
Paul Stewartb50f0b92011-05-16 16:31:42 -070027#include "shill/manager.h"
Chris Masone46eaaf52011-05-24 13:08:30 -070028#include "shill/mock_control.h"
Darin Petkovafa6fc42011-06-21 16:21:08 -070029#include "shill/mock_glib.h"
Chris Masone2ae797d2011-08-23 20:41:00 -070030#include "shill/mock_manager.h"
Thieu Le3426c8f2012-01-11 17:35:11 -080031#include "shill/mock_metrics.h"
Paul Stewart8c116a92012-05-02 18:30:03 -070032#include "shill/mock_modem_info.h"
33#include "shill/mock_routing_table.h"
Paul Stewart9a908082011-08-31 12:18:48 -070034#include "shill/mock_rtnl_handler.h"
Darin Petkov633ac6f2011-07-08 13:56:13 -070035#include "shill/mock_sockets.h"
Paul Stewart8c116a92012-05-02 18:30:03 -070036#include "shill/mock_vpn_provider.h"
Darin Petkove4b27022012-05-16 13:28:50 +020037#include "shill/mock_wimax_provider.h"
Chris Masone2aa97072011-08-09 17:35:08 -070038#include "shill/rtnl_message.h"
Darin Petkovc63dcf02012-05-24 11:51:43 +020039#include "shill/wimax.h"
Chris Masone9be4a9d2011-05-16 15:44:09 -070040
Eric Shienbrood3e20a232012-02-16 11:35:56 -050041using base::Callback;
Darin Petkove6193c02011-08-11 12:42:40 -070042using std::map;
Darin Petkov633ac6f2011-07-08 13:56:13 -070043using std::string;
Paul Stewart9a908082011-08-31 12:18:48 -070044using std::vector;
Darin Petkov633ac6f2011-07-08 13:56:13 -070045using testing::_;
Gary Morain41780232012-07-31 15:08:31 -070046using testing::DoAll;
47using testing::ElementsAreArray;
Paul Stewart8c116a92012-05-02 18:30:03 -070048using testing::Mock;
Gary Morain41780232012-07-31 15:08:31 -070049using testing::NotNull;
Darin Petkov633ac6f2011-07-08 13:56:13 -070050using testing::Return;
Paul Stewart9a908082011-08-31 12:18:48 -070051using testing::StrictMock;
Darin Petkov633ac6f2011-07-08 13:56:13 -070052using testing::Test;
53
Chris Masone9be4a9d2011-05-16 15:44:09 -070054namespace shill {
Darin Petkov633ac6f2011-07-08 13:56:13 -070055
Paul Stewart050cfc02012-07-06 20:38:54 -070056class TestEventDispatcherForDeviceInfo : public EventDispatcher {
Darin Petkov633ac6f2011-07-08 13:56:13 -070057 public:
Paul Stewart26b327e2011-10-19 11:38:09 -070058 virtual IOHandler *CreateInputHandler(
mukesh agrawal1830fa12011-09-26 14:31:40 -070059 int /*fd*/,
Eric Shienbrood3e20a232012-02-16 11:35:56 -050060 const Callback<void(InputData*)> &/*callback*/) {
Darin Petkov633ac6f2011-07-08 13:56:13 -070061 return NULL;
62 }
Paul Stewart050cfc02012-07-06 20:38:54 -070063 MOCK_METHOD2(PostDelayedTask, bool(const base::Closure &task,
64 int64 delay_ms));
Darin Petkov633ac6f2011-07-08 13:56:13 -070065};
Chris Masone9be4a9d2011-05-16 15:44:09 -070066
67class DeviceInfoTest : public Test {
68 public:
69 DeviceInfoTest()
Thieu Le3426c8f2012-01-11 17:35:11 -080070 : manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
71 device_info_(&control_interface_, &dispatcher_, &metrics_, &manager_) {
Chris Masone9be4a9d2011-05-16 15:44:09 -070072 }
Paul Stewartca876ee2012-04-21 08:55:58 -070073 virtual ~DeviceInfoTest() {}
Darin Petkov633ac6f2011-07-08 13:56:13 -070074
Paul Stewart9a908082011-08-31 12:18:48 -070075 virtual void SetUp() {
76 device_info_.rtnl_handler_ = &rtnl_handler_;
Paul Stewart8c116a92012-05-02 18:30:03 -070077 device_info_.routing_table_ = &routing_table_;
Paul Stewart9a908082011-08-31 12:18:48 -070078 }
79
Paul Stewart8c116a92012-05-02 18:30:03 -070080 IPAddress CreateInterfaceAddress() {
81 // Create an IP address entry (as if left-over from a previous connection
82 // manager).
83 IPAddress address(IPAddress::kFamilyIPv4);
84 EXPECT_TRUE(address.SetAddressFromString(kTestIPAddress0));
85 address.set_prefix(kTestIPAddressPrefix0);
86 vector<DeviceInfo::AddressData> &addresses =
87 device_info_.infos_[kTestDeviceIndex].ip_addresses;
88 addresses.push_back(DeviceInfo::AddressData(address, 0, RT_SCOPE_UNIVERSE));
89 EXPECT_EQ(1, addresses.size());
90 return address;
91 }
92
93 DeviceRefPtr CreateDevice(const std::string &link_name,
94 const std::string &address,
95 int interface_index,
96 Technology::Identifier technology) {
97 return device_info_.CreateDevice(link_name, address, interface_index,
98 technology);
99 }
100
Paul Stewart050cfc02012-07-06 20:38:54 -0700101 virtual std::set<int> &GetDelayedDevices() {
102 return device_info_.delayed_devices_;
103 }
104
Paul Stewart1ac4e842012-07-10 12:58:12 -0700105 int GetDelayedDeviceCreationMilliseconds() {
Paul Stewart050cfc02012-07-06 20:38:54 -0700106 return DeviceInfo::kDelayedDeviceCreationSeconds * 1000;
107 }
Paul Stewart8c116a92012-05-02 18:30:03 -0700108
Paul Stewart1ac4e842012-07-10 12:58:12 -0700109 int GetRequestLinkStatisticsIntervalMilliseconds() {
110 return DeviceInfo::kRequestLinkStatisticsIntervalSeconds * 1000;
111 }
112
Gary Morain41780232012-07-31 15:08:31 -0700113 void SetSockets() {
114 mock_sockets_ = new MockSockets();
115 device_info_.set_sockets(mock_sockets_);
116 }
117
Paul Stewarta3c56f92011-05-26 07:08:52 -0700118 protected:
Chris Masoneb2e326b2011-07-12 13:28:51 -0700119 static const int kTestDeviceIndex;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700120 static const char kTestDeviceName[];
Han Shenfc349252012-08-30 11:36:04 -0700121 static const uint8_t kTestMACAddress[];
Paul Stewart9a908082011-08-31 12:18:48 -0700122 static const char kTestIPAddress0[];
123 static const int kTestIPAddressPrefix0;
124 static const char kTestIPAddress1[];
125 static const int kTestIPAddressPrefix1;
126 static const char kTestIPAddress2[];
127 static const char kTestIPAddress3[];
128 static const char kTestIPAddress4[];
Paul Stewart05a42c22012-08-02 16:47:21 -0700129 static const char kTestIPAddress5[];
Paul Stewart1ac4e842012-07-10 12:58:12 -0700130 static const int kReceiveByteCount;
131 static const int kTransmitByteCount;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700132
Paul Stewart9a908082011-08-31 12:18:48 -0700133 RTNLMessage *BuildLinkMessage(RTNLMessage::Mode mode);
Paul Stewarte81eb702012-04-11 15:04:53 -0700134 RTNLMessage *BuildLinkMessageWithInterfaceName(RTNLMessage::Mode mode,
135 const string &interface_name);
Paul Stewart9a908082011-08-31 12:18:48 -0700136 RTNLMessage *BuildAddressMessage(RTNLMessage::Mode mode,
137 const IPAddress &address,
138 unsigned char flags,
139 unsigned char scope);
Chris Masone2aa97072011-08-09 17:35:08 -0700140 void SendMessageToDeviceInfo(const RTNLMessage &message);
Darin Petkov633ac6f2011-07-08 13:56:13 -0700141
Darin Petkovafa6fc42011-06-21 16:21:08 -0700142 MockGLib glib_;
Chris Masone46eaaf52011-05-24 13:08:30 -0700143 MockControl control_interface_;
Thieu Le3426c8f2012-01-11 17:35:11 -0800144 MockMetrics metrics_;
Paul Stewart9a908082011-08-31 12:18:48 -0700145 StrictMock<MockManager> manager_;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700146 DeviceInfo device_info_;
Paul Stewart050cfc02012-07-06 20:38:54 -0700147 TestEventDispatcherForDeviceInfo dispatcher_;
Paul Stewart8c116a92012-05-02 18:30:03 -0700148 MockRoutingTable routing_table_;
Paul Stewart9a908082011-08-31 12:18:48 -0700149 StrictMock<MockRTNLHandler> rtnl_handler_;
Gary Morain41780232012-07-31 15:08:31 -0700150 MockSockets *mock_sockets_; // Owned by DeviceInfo.
Chris Masone9be4a9d2011-05-16 15:44:09 -0700151};
152
Chris Masoneb2e326b2011-07-12 13:28:51 -0700153const int DeviceInfoTest::kTestDeviceIndex = 123456;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700154const char DeviceInfoTest::kTestDeviceName[] = "test-device";
Han Shenfc349252012-08-30 11:36:04 -0700155const uint8_t DeviceInfoTest::kTestMACAddress[] = {
156 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
Paul Stewart9a908082011-08-31 12:18:48 -0700157const char DeviceInfoTest::kTestIPAddress0[] = "192.168.1.1";
158const int DeviceInfoTest::kTestIPAddressPrefix0 = 24;
159const char DeviceInfoTest::kTestIPAddress1[] = "fe80::1aa9:5ff:abcd:1234";
160const int DeviceInfoTest::kTestIPAddressPrefix1 = 64;
161const char DeviceInfoTest::kTestIPAddress2[] = "fe80::1aa9:5ff:abcd:1235";
162const char DeviceInfoTest::kTestIPAddress3[] = "fe80::1aa9:5ff:abcd:1236";
163const char DeviceInfoTest::kTestIPAddress4[] = "fe80::1aa9:5ff:abcd:1237";
Paul Stewart05a42c22012-08-02 16:47:21 -0700164const char DeviceInfoTest::kTestIPAddress5[] = "192.168.1.2";
Paul Stewart1ac4e842012-07-10 12:58:12 -0700165const int DeviceInfoTest::kReceiveByteCount = 1234;
166const int DeviceInfoTest::kTransmitByteCount = 5678;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700167
Paul Stewarte81eb702012-04-11 15:04:53 -0700168RTNLMessage *DeviceInfoTest::BuildLinkMessageWithInterfaceName(
169 RTNLMessage::Mode mode, const string &interface_name) {
Paul Stewart9a908082011-08-31 12:18:48 -0700170 RTNLMessage *message = new RTNLMessage(
171 RTNLMessage::kTypeLink,
172 mode,
173 0,
174 0,
175 0,
176 kTestDeviceIndex,
Paul Stewart7355ce12011-09-02 10:47:01 -0700177 IPAddress::kFamilyIPv4);
Chris Masone2aa97072011-08-09 17:35:08 -0700178 message->SetAttribute(static_cast<uint16>(IFLA_IFNAME),
Paul Stewarte81eb702012-04-11 15:04:53 -0700179 ByteString(interface_name, true));
Paul Stewart9a908082011-08-31 12:18:48 -0700180 ByteString test_address(kTestMACAddress, sizeof(kTestMACAddress));
Chris Masone626719f2011-08-18 16:58:48 -0700181 message->SetAttribute(IFLA_ADDRESS, test_address);
Chris Masone2aa97072011-08-09 17:35:08 -0700182 return message;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700183}
184
Paul Stewarte81eb702012-04-11 15:04:53 -0700185RTNLMessage *DeviceInfoTest::BuildLinkMessage(RTNLMessage::Mode mode) {
186 return BuildLinkMessageWithInterfaceName(mode, kTestDeviceName);
187}
188
Paul Stewart9a908082011-08-31 12:18:48 -0700189RTNLMessage *DeviceInfoTest::BuildAddressMessage(RTNLMessage::Mode mode,
190 const IPAddress &address,
191 unsigned char flags,
192 unsigned char scope) {
193 RTNLMessage *message = new RTNLMessage(
194 RTNLMessage::kTypeAddress,
195 mode,
196 0,
197 0,
198 0,
199 kTestDeviceIndex,
200 address.family());
201 message->SetAttribute(IFA_ADDRESS, address.address());
202 message->set_address_status(
203 RTNLMessage::AddressStatus(address.prefix(), flags, scope));
204 return message;
205}
206
Chris Masone2aa97072011-08-09 17:35:08 -0700207void DeviceInfoTest::SendMessageToDeviceInfo(const RTNLMessage &message) {
Paul Stewart9a908082011-08-31 12:18:48 -0700208 if (message.type() == RTNLMessage::kTypeLink) {
209 device_info_.LinkMsgHandler(message);
210 } else if (message.type() == RTNLMessage::kTypeAddress) {
211 device_info_.AddressMsgHandler(message);
212 } else {
213 NOTREACHED();
214 }
215}
216
217MATCHER_P(IsIPAddress, address, "") {
218 // NB: IPAddress objects don't support the "==" operator as per style, so
219 // we need a custom matcher.
220 return address.Equals(arg);
Darin Petkov633ac6f2011-07-08 13:56:13 -0700221}
222
Paul Stewart8c116a92012-05-02 18:30:03 -0700223TEST_F(DeviceInfoTest, StartStop) {
224 EXPECT_FALSE(device_info_.link_listener_.get());
225 EXPECT_FALSE(device_info_.address_listener_.get());
226 EXPECT_TRUE(device_info_.infos_.empty());
227
228 EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestLink |
229 RTNLHandler::kRequestAddr));
Paul Stewart1ac4e842012-07-10 12:58:12 -0700230 EXPECT_CALL(dispatcher_, PostDelayedTask(
231 _, GetRequestLinkStatisticsIntervalMilliseconds()));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700232 device_info_.Start();
Paul Stewart8c116a92012-05-02 18:30:03 -0700233 EXPECT_TRUE(device_info_.link_listener_.get());
234 EXPECT_TRUE(device_info_.address_listener_.get());
235 EXPECT_TRUE(device_info_.infos_.empty());
236 Mock::VerifyAndClearExpectations(&rtnl_handler_);
237
238 CreateInterfaceAddress();
239 EXPECT_FALSE(device_info_.infos_.empty());
240
241 device_info_.Stop();
242 EXPECT_FALSE(device_info_.link_listener_.get());
243 EXPECT_FALSE(device_info_.address_listener_.get());
244 EXPECT_TRUE(device_info_.infos_.empty());
245}
246
Paul Stewart1ac4e842012-07-10 12:58:12 -0700247TEST_F(DeviceInfoTest, RequestLinkStatistics) {
248 EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestLink));
249 EXPECT_CALL(dispatcher_, PostDelayedTask(
250 _, GetRequestLinkStatisticsIntervalMilliseconds()));
251 device_info_.RequestLinkStatistics();
252}
253
Paul Stewart8c116a92012-05-02 18:30:03 -0700254TEST_F(DeviceInfoTest, DeviceEnumeration) {
Paul Stewart9a908082011-08-31 12:18:48 -0700255 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
Darin Petkove6193c02011-08-11 12:42:40 -0700256 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_LOWER_UP, 0));
257 EXPECT_FALSE(device_info_.GetDevice(kTestDeviceIndex).get());
Darin Petkovf8046b82012-04-24 16:29:23 +0200258 EXPECT_EQ(-1, device_info_.GetIndex(kTestDeviceName));
Darin Petkove6193c02011-08-11 12:42:40 -0700259 SendMessageToDeviceInfo(*message);
260 EXPECT_TRUE(device_info_.GetDevice(kTestDeviceIndex).get());
261 unsigned int flags = 0;
262 EXPECT_TRUE(device_info_.GetFlags(kTestDeviceIndex, &flags));
263 EXPECT_EQ(IFF_LOWER_UP, flags);
Darin Petkove3e1cfa2011-08-11 13:41:17 -0700264 ByteString address;
Paul Stewart32852962011-08-30 14:06:53 -0700265 EXPECT_TRUE(device_info_.GetMACAddress(kTestDeviceIndex, &address));
Darin Petkove3e1cfa2011-08-11 13:41:17 -0700266 EXPECT_FALSE(address.IsEmpty());
Paul Stewart9a908082011-08-31 12:18:48 -0700267 EXPECT_TRUE(address.Equals(ByteString(kTestMACAddress,
268 sizeof(kTestMACAddress))));
Darin Petkovf8046b82012-04-24 16:29:23 +0200269 EXPECT_EQ(kTestDeviceIndex, device_info_.GetIndex(kTestDeviceName));
Paul Stewarta3c56f92011-05-26 07:08:52 -0700270
Paul Stewart9a908082011-08-31 12:18:48 -0700271 message.reset(BuildLinkMessage(RTNLMessage::kModeAdd));
Darin Petkove6193c02011-08-11 12:42:40 -0700272 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_UP | IFF_RUNNING, 0));
273 SendMessageToDeviceInfo(*message);
274 EXPECT_TRUE(device_info_.GetFlags(kTestDeviceIndex, &flags));
275 EXPECT_EQ(IFF_UP | IFF_RUNNING, flags);
Paul Stewartb50f0b92011-05-16 16:31:42 -0700276
Paul Stewart9a908082011-08-31 12:18:48 -0700277 message.reset(BuildLinkMessage(RTNLMessage::kModeDelete));
Paul Stewart8c116a92012-05-02 18:30:03 -0700278 EXPECT_CALL(manager_, DeregisterDevice(_)).Times(1);
Darin Petkove6193c02011-08-11 12:42:40 -0700279 SendMessageToDeviceInfo(*message);
280 EXPECT_FALSE(device_info_.GetDevice(kTestDeviceIndex).get());
281 EXPECT_FALSE(device_info_.GetFlags(kTestDeviceIndex, NULL));
Darin Petkovf8046b82012-04-24 16:29:23 +0200282 EXPECT_EQ(-1, device_info_.GetIndex(kTestDeviceName));
Paul Stewart8c116a92012-05-02 18:30:03 -0700283}
Paul Stewarta3c56f92011-05-26 07:08:52 -0700284
Paul Stewart1ac4e842012-07-10 12:58:12 -0700285TEST_F(DeviceInfoTest, GetByteCounts) {
286 uint64 rx_bytes, tx_bytes;
287 EXPECT_FALSE(device_info_.GetByteCounts(
288 kTestDeviceIndex, &rx_bytes, &tx_bytes));
289
290 // No link statistics in the message.
291 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
292 SendMessageToDeviceInfo(*message);
293 EXPECT_TRUE(device_info_.GetByteCounts(
294 kTestDeviceIndex, &rx_bytes, &tx_bytes));
295 EXPECT_EQ(0, rx_bytes);
296 EXPECT_EQ(0, tx_bytes);
297
298 // Short link statistics message.
299 message.reset(BuildLinkMessage(RTNLMessage::kModeAdd));
300 struct rtnl_link_stats64 stats;
301 memset(&stats, 0, sizeof(stats));
302 stats.rx_bytes = kReceiveByteCount;
303 stats.tx_bytes = kTransmitByteCount;
304 ByteString stats_bytes0(reinterpret_cast<const unsigned char*>(&stats),
305 sizeof(stats) - 1);
306 message->SetAttribute(IFLA_STATS64, stats_bytes0);
307 SendMessageToDeviceInfo(*message);
308 EXPECT_TRUE(device_info_.GetByteCounts(
309 kTestDeviceIndex, &rx_bytes, &tx_bytes));
310 EXPECT_EQ(0, rx_bytes);
311 EXPECT_EQ(0, tx_bytes);
312
313 // Correctly sized link statistics message.
314 message.reset(BuildLinkMessage(RTNLMessage::kModeAdd));
315 ByteString stats_bytes1(reinterpret_cast<const unsigned char*>(&stats),
316 sizeof(stats));
317 message->SetAttribute(IFLA_STATS64, stats_bytes1);
318 SendMessageToDeviceInfo(*message);
319 EXPECT_TRUE(device_info_.GetByteCounts(
320 kTestDeviceIndex, &rx_bytes, &tx_bytes));
321 EXPECT_EQ(kReceiveByteCount, rx_bytes);
322 EXPECT_EQ(kTransmitByteCount, tx_bytes);
323}
324
Paul Stewart8c116a92012-05-02 18:30:03 -0700325TEST_F(DeviceInfoTest, CreateDeviceCellular) {
326 IPAddress address = CreateInterfaceAddress();
327
328 // A cellular device should be offered to ModemInfo.
329 StrictMock<MockModemInfo> modem_info;
330 EXPECT_CALL(manager_, modem_info()).WillOnce(Return(&modem_info));
331 EXPECT_CALL(modem_info, OnDeviceInfoAvailable(kTestDeviceName)).Times(1);
332 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
333 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
334 IsIPAddress(address)));
335 EXPECT_FALSE(CreateDevice(
336 kTestDeviceName, "address", kTestDeviceIndex, Technology::kCellular));
337}
338
Darin Petkove4b27022012-05-16 13:28:50 +0200339TEST_F(DeviceInfoTest, CreateDeviceWiMax) {
340 IPAddress address = CreateInterfaceAddress();
341
342 // A WiMax device should be offered to WiMaxProvider.
343 StrictMock<MockWiMaxProvider> wimax_provider;
344 EXPECT_CALL(manager_, wimax_provider()).WillOnce(Return(&wimax_provider));
345 EXPECT_CALL(wimax_provider, OnDeviceInfoAvailable(kTestDeviceName)).Times(1);
346 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
347 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
348 IsIPAddress(address)));
349 EXPECT_FALSE(CreateDevice(
350 kTestDeviceName, "address", kTestDeviceIndex, Technology::kWiMax));
351}
352
Paul Stewart8c116a92012-05-02 18:30:03 -0700353TEST_F(DeviceInfoTest, CreateDeviceEthernet) {
354 IPAddress address = CreateInterfaceAddress();
355
356 // An Ethernet device should cause routes and addresses to be flushed.
357 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
358 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
359 IsIPAddress(address)));
360 DeviceRefPtr device = CreateDevice(
361 kTestDeviceName, "address", kTestDeviceIndex, Technology::kEthernet);
362 EXPECT_TRUE(device);
363 Mock::VerifyAndClearExpectations(&routing_table_);
364 Mock::VerifyAndClearExpectations(&rtnl_handler_);
365
366 // The Ethernet device destructor notifies the manager.
367 EXPECT_CALL(manager_, UpdateEnabledTechnologies()).Times(1);
368 device = NULL;
369}
370
371TEST_F(DeviceInfoTest, CreateDeviceVirtioEthernet) {
372 IPAddress address = CreateInterfaceAddress();
373
374 // VirtioEthernet is identical to Ethernet from the perspective of this test.
375 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
376 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
377 IsIPAddress(address)));
378 DeviceRefPtr device = CreateDevice(
379 kTestDeviceName, "address", kTestDeviceIndex,
380 Technology::kVirtioEthernet);
381 EXPECT_TRUE(device);
382 Mock::VerifyAndClearExpectations(&routing_table_);
383 Mock::VerifyAndClearExpectations(&rtnl_handler_);
384
385 // The Ethernet device destructor notifies the manager.
386 EXPECT_CALL(manager_, UpdateEnabledTechnologies()).Times(1);
387 device = NULL;
388}
389
390TEST_F(DeviceInfoTest, CreateDeviceWiFi) {
391 IPAddress address = CreateInterfaceAddress();
392
393 // WiFi looks a lot like Ethernet too.
394 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
395 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
396 IsIPAddress(address)));
397 EXPECT_TRUE(CreateDevice(
398 kTestDeviceName, "address", kTestDeviceIndex, Technology::kWifi));
399}
400
401TEST_F(DeviceInfoTest, CreateDeviceTunnelAccepted) {
402 IPAddress address = CreateInterfaceAddress();
403
404 // A VPN device should be offered to VPNProvider.
405 StrictMock<MockVPNProvider> vpn_provider;
406 EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&vpn_provider));
407 EXPECT_CALL(vpn_provider,
408 OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
409 .WillOnce(Return(true));
410 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
411 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
412 IsIPAddress(address)));
413 EXPECT_CALL(rtnl_handler_, RemoveInterface(_)).Times(0);
414 EXPECT_FALSE(CreateDevice(
415 kTestDeviceName, "address", kTestDeviceIndex, Technology::kTunnel));
416}
417
418TEST_F(DeviceInfoTest, CreateDeviceTunnelRejected) {
419 IPAddress address = CreateInterfaceAddress();
420
421 // A VPN device should be offered to VPNProvider.
422 StrictMock<MockVPNProvider> vpn_provider;
423 EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&vpn_provider));
424 EXPECT_CALL(vpn_provider,
425 OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
426 .WillOnce(Return(false));
427 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
428 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
429 IsIPAddress(address)));
430 // Since the device was rejected by the VPNProvider, DeviceInfo will
431 // remove the interface.
432 EXPECT_CALL(rtnl_handler_, RemoveInterface(kTestDeviceIndex)).Times(1);
433 EXPECT_FALSE(CreateDevice(
434 kTestDeviceName, "address", kTestDeviceIndex, Technology::kTunnel));
435}
436
437TEST_F(DeviceInfoTest, CreateDevicePPP) {
438 IPAddress address = CreateInterfaceAddress();
439
440 // A VPN device should be offered to VPNProvider.
441 StrictMock<MockVPNProvider> vpn_provider;
442 EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&vpn_provider));
443 EXPECT_CALL(vpn_provider,
444 OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
445 .WillOnce(Return(false));
446 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
447 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
448 IsIPAddress(address)));
449 // We do not remove PPP interfaces even if the provider does not accept it.
450 EXPECT_CALL(rtnl_handler_, RemoveInterface(_)).Times(0);
451 EXPECT_FALSE(CreateDevice(
452 kTestDeviceName, "address", kTestDeviceIndex, Technology::kPPP));
453}
454
455TEST_F(DeviceInfoTest, CreateDeviceLoopback) {
456 // A loopback device should be brought up, and nothing else done to it.
457 EXPECT_CALL(routing_table_, FlushRoutes(_)).Times(0);
458 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(_, _)).Times(0);
459 EXPECT_CALL(rtnl_handler_,
460 SetInterfaceFlags(kTestDeviceIndex, IFF_UP, IFF_UP)).Times(1);
461 EXPECT_FALSE(CreateDevice(
462 kTestDeviceName, "address", kTestDeviceIndex, Technology::kLoopback));
463}
464
Paul Stewart050cfc02012-07-06 20:38:54 -0700465TEST_F(DeviceInfoTest, CreateDeviceCDCEthernet) {
466 // A cdc_ether device should be postponed to a task.
467 EXPECT_CALL(manager_, modem_info()).Times(0);
468 EXPECT_CALL(routing_table_, FlushRoutes(_)).Times(0);
469 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(_, _)).Times(0);
470 EXPECT_CALL(dispatcher_,
Paul Stewart1ac4e842012-07-10 12:58:12 -0700471 PostDelayedTask(_, GetDelayedDeviceCreationMilliseconds()));
Paul Stewart050cfc02012-07-06 20:38:54 -0700472 EXPECT_TRUE(GetDelayedDevices().empty());
473 EXPECT_FALSE(CreateDevice(
474 kTestDeviceName, "address", kTestDeviceIndex, Technology::kCDCEthernet));
475 EXPECT_FALSE(GetDelayedDevices().empty());
476 EXPECT_EQ(1, GetDelayedDevices().size());
477 EXPECT_EQ(kTestDeviceIndex, *GetDelayedDevices().begin());
478}
479
Paul Stewart8c116a92012-05-02 18:30:03 -0700480TEST_F(DeviceInfoTest, CreateDeviceUnknown) {
481 IPAddress address = CreateInterfaceAddress();
482
483 // An unknown (blacklisted, unhandled, etc) device won't be flushed or
484 // registered.
485 EXPECT_CALL(routing_table_, FlushRoutes(_)).Times(0);
486 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(_, _)).Times(0);
487 EXPECT_TRUE(CreateDevice(
488 kTestDeviceName, "address", kTestDeviceIndex, Technology::kUnknown));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700489}
490
mukesh agrawal8f317b62011-07-15 11:53:23 -0700491TEST_F(DeviceInfoTest, DeviceBlackList) {
492 device_info_.AddDeviceToBlackList(kTestDeviceName);
Paul Stewart9a908082011-08-31 12:18:48 -0700493 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
Darin Petkove6193c02011-08-11 12:42:40 -0700494 SendMessageToDeviceInfo(*message);
mukesh agrawal8f317b62011-07-15 11:53:23 -0700495
Darin Petkove6193c02011-08-11 12:42:40 -0700496 DeviceRefPtr device = device_info_.GetDevice(kTestDeviceIndex);
497 ASSERT_TRUE(device.get());
Joshua Krollda798622012-06-05 12:30:48 -0700498 EXPECT_TRUE(device->technology() == Technology::kBlacklisted);
mukesh agrawal8f317b62011-07-15 11:53:23 -0700499}
500
Paul Stewart9a908082011-08-31 12:18:48 -0700501TEST_F(DeviceInfoTest, DeviceAddressList) {
Paul Stewart9a908082011-08-31 12:18:48 -0700502 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
503 SendMessageToDeviceInfo(*message);
504
505 vector<DeviceInfo::AddressData> addresses;
506 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
507 EXPECT_TRUE(addresses.empty());
508
509 // Add an address to the device address list
Paul Stewart7355ce12011-09-02 10:47:01 -0700510 IPAddress ip_address0(IPAddress::kFamilyIPv4);
Paul Stewart9a908082011-08-31 12:18:48 -0700511 EXPECT_TRUE(ip_address0.SetAddressFromString(kTestIPAddress0));
512 ip_address0.set_prefix(kTestIPAddressPrefix0);
513 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address0, 0, 0));
514 SendMessageToDeviceInfo(*message);
515 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
516 EXPECT_EQ(1, addresses.size());
517 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
518
519 // Re-adding the same address shouldn't cause the address list to change
520 SendMessageToDeviceInfo(*message);
521 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
522 EXPECT_EQ(1, addresses.size());
523 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
524
525 // Adding a new address should expand the list
Paul Stewart7355ce12011-09-02 10:47:01 -0700526 IPAddress ip_address1(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700527 EXPECT_TRUE(ip_address1.SetAddressFromString(kTestIPAddress1));
528 ip_address1.set_prefix(kTestIPAddressPrefix1);
529 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address1, 0, 0));
530 SendMessageToDeviceInfo(*message);
531 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
532 EXPECT_EQ(2, addresses.size());
533 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
534 EXPECT_TRUE(ip_address1.Equals(addresses[1].address));
535
536 // Deleting an address should reduce the list
537 message.reset(BuildAddressMessage(RTNLMessage::kModeDelete,
538 ip_address0,
539 0,
540 0));
541 SendMessageToDeviceInfo(*message);
542 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
543 EXPECT_EQ(1, addresses.size());
544 EXPECT_TRUE(ip_address1.Equals(addresses[0].address));
545
546 // Delete last item
547 message.reset(BuildAddressMessage(RTNLMessage::kModeDelete,
548 ip_address1,
549 0,
550 0));
551 SendMessageToDeviceInfo(*message);
552 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
553 EXPECT_TRUE(addresses.empty());
554
555 // Delete device
556 message.reset(BuildLinkMessage(RTNLMessage::kModeDelete));
Paul Stewart8c116a92012-05-02 18:30:03 -0700557 EXPECT_CALL(manager_, DeregisterDevice(_)).Times(1);
Paul Stewart9a908082011-08-31 12:18:48 -0700558 SendMessageToDeviceInfo(*message);
559
560 // Should be able to handle message for interface that doesn't exist
561 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address0, 0, 0));
562 SendMessageToDeviceInfo(*message);
563 EXPECT_FALSE(device_info_.GetDevice(kTestDeviceIndex).get());
Paul Stewart9a908082011-08-31 12:18:48 -0700564}
565
566TEST_F(DeviceInfoTest, FlushAddressList) {
Paul Stewart9a908082011-08-31 12:18:48 -0700567 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
568 SendMessageToDeviceInfo(*message);
569
Paul Stewart7355ce12011-09-02 10:47:01 -0700570 IPAddress address1(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700571 EXPECT_TRUE(address1.SetAddressFromString(kTestIPAddress1));
572 address1.set_prefix(kTestIPAddressPrefix1);
573 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
574 address1,
575 0,
576 RT_SCOPE_UNIVERSE));
577 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700578 IPAddress address2(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700579 EXPECT_TRUE(address2.SetAddressFromString(kTestIPAddress2));
580 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
581 address2,
582 IFA_F_TEMPORARY,
583 RT_SCOPE_UNIVERSE));
584 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700585 IPAddress address3(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700586 EXPECT_TRUE(address3.SetAddressFromString(kTestIPAddress3));
587 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
588 address3,
589 0,
590 RT_SCOPE_LINK));
591 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700592 IPAddress address4(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700593 EXPECT_TRUE(address4.SetAddressFromString(kTestIPAddress4));
594 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
595 address4,
596 IFA_F_PERMANENT,
597 RT_SCOPE_UNIVERSE));
598 SendMessageToDeviceInfo(*message);
599
600 // DeviceInfo now has 4 addresses associated with it, but only two of
601 // them are valid for flush.
602 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
603 IsIPAddress(address1)));
604 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
605 IsIPAddress(address2)));
606 device_info_.FlushAddresses(kTestDeviceIndex);
Paul Stewart9a908082011-08-31 12:18:48 -0700607}
608
Paul Stewart05a42c22012-08-02 16:47:21 -0700609TEST_F(DeviceInfoTest, HasOtherAddress) {
610 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
611 SendMessageToDeviceInfo(*message);
612
613 IPAddress address0(IPAddress::kFamilyIPv4);
614 EXPECT_TRUE(address0.SetAddressFromString(kTestIPAddress0));
615
616 // There are no addresses on this interface.
617 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address0));
618
619 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
620 address0,
621 0,
622 RT_SCOPE_UNIVERSE));
623 SendMessageToDeviceInfo(*message);
624
625 IPAddress address1(IPAddress::kFamilyIPv6);
626 EXPECT_TRUE(address1.SetAddressFromString(kTestIPAddress1));
627 address1.set_prefix(kTestIPAddressPrefix1);
628 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
629 address1,
630 0,
631 RT_SCOPE_LINK));
632 SendMessageToDeviceInfo(*message);
633
634 IPAddress address2(IPAddress::kFamilyIPv6);
635 EXPECT_TRUE(address2.SetAddressFromString(kTestIPAddress2));
636 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
637 address2,
638 IFA_F_TEMPORARY,
639 RT_SCOPE_UNIVERSE));
640 SendMessageToDeviceInfo(*message);
641
642 IPAddress address3(IPAddress::kFamilyIPv6);
643 EXPECT_TRUE(address3.SetAddressFromString(kTestIPAddress3));
644
645 // The only IPv6 addresses on this interface are either flagged as
646 // temporary, or they are not universally scoped.
647 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address3));
648
649
650 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
651 address3,
652 0,
653 RT_SCOPE_UNIVERSE));
654 SendMessageToDeviceInfo(*message);
655
656 // address0 is on this interface.
657 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address0));
658 // address1 is on this interface.
659 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address1));
660 // address2 is on this interface.
661 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address2));
662 // address3 is on this interface.
663 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address3));
664
665 IPAddress address4(IPAddress::kFamilyIPv6);
666 EXPECT_TRUE(address4.SetAddressFromString(kTestIPAddress4));
667
668 // address4 is not on this interface, but address3 is, and is a qualified
669 // IPv6 address.
670 EXPECT_TRUE(device_info_.HasOtherAddress(kTestDeviceIndex, address4));
671
672 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
673 address4,
674 IFA_F_PERMANENT,
675 RT_SCOPE_UNIVERSE));
676 SendMessageToDeviceInfo(*message);
677
678 // address4 is now on this interface.
679 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address4));
680
681 IPAddress address5(IPAddress::kFamilyIPv4);
682 EXPECT_TRUE(address5.SetAddressFromString(kTestIPAddress5));
683 // address5 is not on this interface, but address0 is.
684 EXPECT_TRUE(device_info_.HasOtherAddress(kTestDeviceIndex, address5));
685
686 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
687 address5,
688 IFA_F_PERMANENT,
689 RT_SCOPE_UNIVERSE));
690 SendMessageToDeviceInfo(*message);
691
692 // address5 is now on this interface.
693 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address5));
694}
695
Thieu Leb27beee2012-04-20 09:19:06 -0700696TEST_F(DeviceInfoTest, HasSubdir) {
Thieu Le8f1c8352012-04-16 11:02:12 -0700697 ScopedTempDir temp_dir;
698 EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
Thieu Leb27beee2012-04-20 09:19:06 -0700699 EXPECT_TRUE(file_util::CreateDirectory(temp_dir.path().Append("child1")));
700 FilePath child2 = temp_dir.path().Append("child2");
701 EXPECT_TRUE(file_util::CreateDirectory(child2));
702 FilePath grandchild = child2.Append("grandchild");
Thieu Le8f1c8352012-04-16 11:02:12 -0700703 EXPECT_TRUE(file_util::CreateDirectory(grandchild));
704 EXPECT_TRUE(file_util::CreateDirectory(grandchild.Append("greatgrandchild")));
Thieu Leb27beee2012-04-20 09:19:06 -0700705 EXPECT_TRUE(DeviceInfo::HasSubdir(temp_dir.path(),
706 FilePath("grandchild")));
707 EXPECT_TRUE(DeviceInfo::HasSubdir(temp_dir.path(),
708 FilePath("greatgrandchild")));
709 EXPECT_FALSE(DeviceInfo::HasSubdir(temp_dir.path(),
710 FilePath("nonexistent")));
Thieu Le8f1c8352012-04-16 11:02:12 -0700711}
712
Gary Morain41780232012-07-31 15:08:31 -0700713TEST_F(DeviceInfoTest, GetMACAddressFromKernelUnknownDevice) {
714 SetSockets();
715 EXPECT_CALL(*mock_sockets_, Socket(PF_INET, SOCK_DGRAM, 0)).Times(0);
716 ByteString mac_address =
717 device_info_.GetMACAddressFromKernel(kTestDeviceIndex);
718 EXPECT_TRUE(mac_address.IsEmpty());
719}
720
721TEST_F(DeviceInfoTest, GetMACAddressFromKernelUnableToOpenSocket) {
722 SetSockets();
723 EXPECT_CALL(*mock_sockets_, Socket(PF_INET, SOCK_DGRAM, 0))
724 .WillOnce(Return(-1));
725 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
726 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_LOWER_UP, 0));
727 SendMessageToDeviceInfo(*message);
728 EXPECT_TRUE(device_info_.GetDevice(kTestDeviceIndex).get());
729 ByteString mac_address =
730 device_info_.GetMACAddressFromKernel(kTestDeviceIndex);
731 EXPECT_TRUE(mac_address.IsEmpty());
732}
733
734TEST_F(DeviceInfoTest, GetMACAddressFromKernelIoctlFails) {
735 SetSockets();
736 const int kFd = 99;
737 EXPECT_CALL(*mock_sockets_, Socket(PF_INET, SOCK_DGRAM, 0))
738 .WillOnce(Return(kFd));
739 EXPECT_CALL(*mock_sockets_, Ioctl(kFd, SIOCGIFHWADDR, NotNull()))
740 .WillOnce(Return(-1));
741 EXPECT_CALL(*mock_sockets_, Close(kFd));
742
743 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
744 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_LOWER_UP, 0));
745 SendMessageToDeviceInfo(*message);
746 EXPECT_TRUE(device_info_.GetDevice(kTestDeviceIndex).get());
747
748 ByteString mac_address =
749 device_info_.GetMACAddressFromKernel(kTestDeviceIndex);
750 EXPECT_TRUE(mac_address.IsEmpty());
751}
752
753MATCHER_P2(IfreqEquals, ifindex, ifname, "") {
754 const struct ifreq *const ifr = static_cast<struct ifreq *>(arg);
755 return (ifr != NULL) &&
756 (ifr->ifr_ifindex == ifindex) &&
757 (strcmp(ifname, ifr->ifr_name) == 0);
758}
759
760ACTION_P(SetIfreq, ifr) {
761 struct ifreq *const ifr_arg = static_cast<struct ifreq *>(arg2);
762 *ifr_arg = ifr;
763}
764
765TEST_F(DeviceInfoTest, GetMACAddressFromKernel) {
766 SetSockets();
767 const int kFd = 99;
768 struct ifreq ifr;
Han Shenfc349252012-08-30 11:36:04 -0700769 static uint8_t kMacAddress[] = {0x00, 0x01, 0x02, 0xaa, 0xbb, 0xcc};
Gary Morain41780232012-07-31 15:08:31 -0700770 memcpy(ifr.ifr_hwaddr.sa_data, kMacAddress, sizeof(kMacAddress));
771 EXPECT_CALL(*mock_sockets_, Socket(PF_INET, SOCK_DGRAM, 0))
772 .WillOnce(Return(kFd));
773 EXPECT_CALL(*mock_sockets_,
774 Ioctl(kFd, SIOCGIFHWADDR,
775 IfreqEquals(kTestDeviceIndex, kTestDeviceName)))
776 .WillOnce(DoAll(SetIfreq(ifr), Return(0)));
777 EXPECT_CALL(*mock_sockets_, Close(kFd));
778
779 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
780 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_LOWER_UP, 0));
781 SendMessageToDeviceInfo(*message);
782 EXPECT_TRUE(device_info_.GetDevice(kTestDeviceIndex).get());
783
784 ByteString mac_address =
785 device_info_.GetMACAddressFromKernel(kTestDeviceIndex);
786 EXPECT_THAT(kMacAddress,
787 ElementsAreArray(mac_address.GetData(), sizeof(kMacAddress)));
788}
789
Paul Stewartca876ee2012-04-21 08:55:58 -0700790class DeviceInfoTechnologyTest : public DeviceInfoTest {
791 public:
Jason Glasgowabc54032012-04-20 16:08:32 -0400792 DeviceInfoTechnologyTest()
793 : DeviceInfoTest(),
794 test_device_name_(kTestDeviceName) {}
Paul Stewartca876ee2012-04-21 08:55:58 -0700795 virtual ~DeviceInfoTechnologyTest() {}
796
797 virtual void SetUp() {
798 temp_dir_.CreateUniqueTempDir();
799 device_info_root_ = temp_dir_.path().Append("sys/class/net");
800 device_info_.device_info_root_ = device_info_root_;
801 // Most tests require that the uevent file exist.
802 CreateInfoFile("uevent", "xxx");
803 }
804
805 Technology::Identifier GetDeviceTechnology() {
Jason Glasgowabc54032012-04-20 16:08:32 -0400806 return device_info_.GetDeviceTechnology(test_device_name_);
Paul Stewartca876ee2012-04-21 08:55:58 -0700807 }
808 FilePath GetInfoPath(const string &name);
809 void CreateInfoFile(const string &name, const string &contents);
810 void CreateInfoSymLink(const string &name, const string &contents);
Jason Glasgowabc54032012-04-20 16:08:32 -0400811 void SetDeviceName(const string &name) {
812 test_device_name_ = name;
813 SetUp();
814 }
Paul Stewartca876ee2012-04-21 08:55:58 -0700815
816 protected:
817 ScopedTempDir temp_dir_;
818 FilePath device_info_root_;
Jason Glasgowabc54032012-04-20 16:08:32 -0400819 string test_device_name_;
Paul Stewartca876ee2012-04-21 08:55:58 -0700820};
821
822FilePath DeviceInfoTechnologyTest::GetInfoPath(const string &name) {
Jason Glasgowabc54032012-04-20 16:08:32 -0400823 return device_info_root_.Append(test_device_name_).Append(name);
Paul Stewartca876ee2012-04-21 08:55:58 -0700824}
825
826void DeviceInfoTechnologyTest::CreateInfoFile(const string &name,
827 const string &contents) {
828 FilePath info_path = GetInfoPath(name);
829 EXPECT_TRUE(file_util::CreateDirectory(info_path.DirName()));
830 string contents_newline(contents + "\n");
831 EXPECT_TRUE(file_util::WriteFile(info_path, contents_newline.c_str(),
832 contents_newline.size()));
833}
834
835void DeviceInfoTechnologyTest::CreateInfoSymLink(const string &name,
836 const string &contents) {
837 FilePath info_path = GetInfoPath(name);
Paul Stewartca876ee2012-04-21 08:55:58 -0700838 EXPECT_TRUE(file_util::CreateDirectory(info_path.DirName()));
839 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath(contents), info_path));
840}
841
842TEST_F(DeviceInfoTechnologyTest, Unknown) {
843 EXPECT_EQ(Technology::kUnknown, GetDeviceTechnology());
844 // Should still be unknown even without a uevent file.
845 EXPECT_TRUE(file_util::Delete(GetInfoPath("uevent"), FALSE));
846 EXPECT_EQ(Technology::kUnknown, GetDeviceTechnology());
847}
848
849TEST_F(DeviceInfoTechnologyTest, Loopback) {
850 CreateInfoFile("type", base::IntToString(ARPHRD_LOOPBACK));
851 EXPECT_EQ(Technology::kLoopback, GetDeviceTechnology());
852}
853
854TEST_F(DeviceInfoTechnologyTest, PPP) {
855 CreateInfoFile("type", base::IntToString(ARPHRD_PPP));
856 EXPECT_EQ(Technology::kPPP, GetDeviceTechnology());
857}
858
859TEST_F(DeviceInfoTechnologyTest, Tunnel) {
860 CreateInfoFile("tun_flags", base::IntToString(IFF_TUN));
861 EXPECT_EQ(Technology::kTunnel, GetDeviceTechnology());
862}
863
864TEST_F(DeviceInfoTechnologyTest, WiFi) {
865 CreateInfoFile("uevent", "DEVTYPE=wlan");
866 EXPECT_EQ(Technology::kWifi, GetDeviceTechnology());
867 CreateInfoFile("uevent", "foo\nDEVTYPE=wlan");
868 EXPECT_EQ(Technology::kWifi, GetDeviceTechnology());
869 CreateInfoFile("type", base::IntToString(ARPHRD_IEEE80211_RADIOTAP));
870 EXPECT_EQ(Technology::kWiFiMonitor, GetDeviceTechnology());
871}
872
873TEST_F(DeviceInfoTechnologyTest, Ethernet) {
874 CreateInfoSymLink("device/driver", "xxx");
875 EXPECT_EQ(Technology::kEthernet, GetDeviceTechnology());
876}
877
Darin Petkove4b27022012-05-16 13:28:50 +0200878TEST_F(DeviceInfoTechnologyTest, WiMax) {
879 CreateInfoSymLink("device/driver", "gdm_wimax");
880 EXPECT_EQ(Technology::kWiMax, GetDeviceTechnology());
881}
882
Paul Stewartca876ee2012-04-21 08:55:58 -0700883TEST_F(DeviceInfoTechnologyTest, CellularGobi1) {
884 CreateInfoSymLink("device/driver", "blah/foo/gobi");
885 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
886}
887
888TEST_F(DeviceInfoTechnologyTest, CellularGobi2) {
889 CreateInfoSymLink("device/driver", "../GobiNet");
890 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
891}
892
893TEST_F(DeviceInfoTechnologyTest, QCUSB) {
894 CreateInfoSymLink("device/driver", "QCUSBNet2k");
895 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
896}
897
898// Modem with absolute driver path with top-level tty file:
899// /sys/class/net/dev0/device -> /sys/devices/virtual/0/00
900// /sys/devices/virtual/0/00/driver -> /drivers/cdc_ether
901// /sys/devices/virtual/0/01/tty [empty directory]
902TEST_F(DeviceInfoTechnologyTest, CDCEtherModem1) {
903 FilePath device_root(temp_dir_.path().Append("sys/devices/virtual/0"));
904 FilePath device_path(device_root.Append("00"));
905 EXPECT_TRUE(file_util::CreateDirectory(device_path));
906 CreateInfoSymLink("device", device_path.value());
907 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
908 device_path.Append("driver")));
909 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/tty")));
910 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
911}
912
913// Modem with relative driver path with top-level tty file.
914// /sys/class/net/dev0/device -> ../../../device_dir/0/00
915// /sys/device_dir/0/00/driver -> /drivers/cdc_ether
916// /sys/device_dir/0/01/tty [empty directory]
917TEST_F(DeviceInfoTechnologyTest, CDCEtherModem2) {
918 CreateInfoSymLink("device", "../../../device_dir/0/00");
919 FilePath device_root(temp_dir_.path().Append("sys/device_dir/0"));
920 FilePath device_path(device_root.Append("00"));
921 EXPECT_TRUE(file_util::CreateDirectory(device_path));
922 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
923 device_path.Append("driver")));
924 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/tty")));
925 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
926}
927
928// Modem with relative driver path with lower-level tty file.
929// /sys/class/net/dev0/device -> ../../../device_dir/0/00
930// /sys/device_dir/0/00/driver -> /drivers/cdc_ether
931// /sys/device_dir/0/01/yyy/tty [empty directory]
932TEST_F(DeviceInfoTechnologyTest, CDCEtherModem3) {
933 CreateInfoSymLink("device", "../../../device_dir/0/00");
934 FilePath device_root(temp_dir_.path().Append("sys/device_dir/0"));
935 FilePath device_path(device_root.Append("00"));
936 EXPECT_TRUE(file_util::CreateDirectory(device_path));
937 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
938 device_path.Append("driver")));
939 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/yyy/tty")));
940 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
941}
942
943TEST_F(DeviceInfoTechnologyTest, CDCEtherNonModem) {
944 CreateInfoSymLink("device", "device_dir");
945 CreateInfoSymLink("device_dir/driver", "cdc_ether");
Paul Stewart050cfc02012-07-06 20:38:54 -0700946 EXPECT_EQ(Technology::kCDCEthernet, GetDeviceTechnology());
Paul Stewartca876ee2012-04-21 08:55:58 -0700947}
948
Jason Glasgowabc54032012-04-20 16:08:32 -0400949TEST_F(DeviceInfoTechnologyTest, PseudoModem) {
950 SetDeviceName("pseudomodem");
951 CreateInfoSymLink("device", "device_dir");
952 CreateInfoSymLink("device_dir/driver", "cdc_ether");
953 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
954
955 SetDeviceName("pseudomodem9");
956 CreateInfoSymLink("device", "device_dir");
957 CreateInfoSymLink("device_dir/driver", "cdc_ether");
958 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
959}
960
Paul Stewart050cfc02012-07-06 20:38:54 -0700961class DeviceInfoForDelayedCreationTest : public DeviceInfo {
962 public:
963 DeviceInfoForDelayedCreationTest(ControlInterface *control_interface,
964 EventDispatcher *dispatcher,
965 Metrics *metrics,
966 Manager *manager)
967 : DeviceInfo(control_interface, dispatcher, metrics, manager) {}
968 MOCK_METHOD4(CreateDevice, DeviceRefPtr(const std::string &link_name,
969 const std::string &address,
970 int interface_index,
971 Technology::Identifier technology));
972 MOCK_METHOD1(GetDeviceTechnology,
973 Technology::Identifier(const string &iface_name));
974};
975
976class DeviceInfoDelayedCreationTest : public DeviceInfoTest {
977 public:
978 DeviceInfoDelayedCreationTest()
979 : DeviceInfoTest(),
980 test_device_info_(
981 &control_interface_, &dispatcher_, &metrics_, &manager_) {}
982 virtual ~DeviceInfoDelayedCreationTest() {}
983
984 virtual std::set<int> &GetDelayedDevices() {
985 return test_device_info_.delayed_devices_;
986 }
987
988 void DelayedDeviceCreationTask() {
989 test_device_info_.DelayedDeviceCreationTask();
990 }
991
992 void AddDelayedDevice() {
993 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
994 EXPECT_CALL(test_device_info_, GetDeviceTechnology(kTestDeviceName))
995 .WillOnce(Return(Technology::kCDCEthernet));
996 EXPECT_CALL(test_device_info_, CreateDevice(
997 kTestDeviceName, _, kTestDeviceIndex, Technology::kCDCEthernet))
998 .WillOnce(Return(DeviceRefPtr()));
999 test_device_info_.AddLinkMsgHandler(*message);
1000 Mock::VerifyAndClearExpectations(&test_device_info_);
1001 // We need to insert the device index ourselves since we have mocked
1002 // out CreateDevice. This insertion is tested in CreateDeviceCDCEthernet
1003 // above.
1004 GetDelayedDevices().insert(kTestDeviceIndex);
1005 }
1006
1007 protected:
1008 DeviceInfoForDelayedCreationTest test_device_info_;
1009};
1010
1011TEST_F(DeviceInfoDelayedCreationTest, NoDevices) {
1012 EXPECT_TRUE(GetDelayedDevices().empty());
1013 EXPECT_CALL(test_device_info_, GetDeviceTechnology(_)).Times(0);
1014 DelayedDeviceCreationTask();
1015}
1016
1017TEST_F(DeviceInfoDelayedCreationTest, EthernetDevice) {
1018 AddDelayedDevice();
1019 EXPECT_CALL(test_device_info_, GetDeviceTechnology(_))
1020 .WillOnce(Return(Technology::kCDCEthernet));
1021 EXPECT_CALL(test_device_info_, CreateDevice(
1022 kTestDeviceName, _, kTestDeviceIndex, Technology::kEthernet))
1023 .WillOnce(Return(DeviceRefPtr()));
1024 DelayedDeviceCreationTask();
1025 EXPECT_TRUE(GetDelayedDevices().empty());
1026}
1027
1028TEST_F(DeviceInfoDelayedCreationTest, CellularDevice) {
1029 AddDelayedDevice();
1030 EXPECT_CALL(test_device_info_, GetDeviceTechnology(_))
1031 .WillOnce(Return(Technology::kCellular));
1032 EXPECT_CALL(test_device_info_, CreateDevice(
1033 kTestDeviceName, _, kTestDeviceIndex, Technology::kCellular))
1034 .WillOnce(Return(DeviceRefPtr()));
1035 DelayedDeviceCreationTask();
1036 EXPECT_TRUE(GetDelayedDevices().empty());
1037}
1038
Chris Masone9be4a9d2011-05-16 15:44:09 -07001039} // namespace shill