blob: ef1bc02507ff0fcd700e789ebea7c559de64cff9 [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)));
Ben Chan4b285862012-10-10 22:52:16 -0700349 device_info_.infos_[kTestDeviceIndex].mac_address =
350 ByteString(kTestMACAddress, sizeof(kTestMACAddress));
Darin Petkove4b27022012-05-16 13:28:50 +0200351 EXPECT_FALSE(CreateDevice(
352 kTestDeviceName, "address", kTestDeviceIndex, Technology::kWiMax));
Ben Chan4b285862012-10-10 22:52:16 -0700353 // The MAC address is clear such that it is obtained via
354 // GetMACAddressFromKernel() instead.
355 EXPECT_TRUE(device_info_.infos_[kTestDeviceIndex].mac_address.IsEmpty());
Darin Petkove4b27022012-05-16 13:28:50 +0200356}
357
Paul Stewart8c116a92012-05-02 18:30:03 -0700358TEST_F(DeviceInfoTest, CreateDeviceEthernet) {
359 IPAddress address = CreateInterfaceAddress();
360
361 // An Ethernet device should cause routes and addresses to be flushed.
362 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
363 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
364 IsIPAddress(address)));
365 DeviceRefPtr device = CreateDevice(
366 kTestDeviceName, "address", kTestDeviceIndex, Technology::kEthernet);
367 EXPECT_TRUE(device);
368 Mock::VerifyAndClearExpectations(&routing_table_);
369 Mock::VerifyAndClearExpectations(&rtnl_handler_);
370
371 // The Ethernet device destructor notifies the manager.
372 EXPECT_CALL(manager_, UpdateEnabledTechnologies()).Times(1);
373 device = NULL;
374}
375
376TEST_F(DeviceInfoTest, CreateDeviceVirtioEthernet) {
377 IPAddress address = CreateInterfaceAddress();
378
379 // VirtioEthernet is identical to Ethernet from the perspective of this test.
380 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
381 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
382 IsIPAddress(address)));
383 DeviceRefPtr device = CreateDevice(
384 kTestDeviceName, "address", kTestDeviceIndex,
385 Technology::kVirtioEthernet);
386 EXPECT_TRUE(device);
387 Mock::VerifyAndClearExpectations(&routing_table_);
388 Mock::VerifyAndClearExpectations(&rtnl_handler_);
389
390 // The Ethernet device destructor notifies the manager.
391 EXPECT_CALL(manager_, UpdateEnabledTechnologies()).Times(1);
392 device = NULL;
393}
394
395TEST_F(DeviceInfoTest, CreateDeviceWiFi) {
396 IPAddress address = CreateInterfaceAddress();
397
398 // WiFi looks a lot like Ethernet too.
399 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
400 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
401 IsIPAddress(address)));
402 EXPECT_TRUE(CreateDevice(
403 kTestDeviceName, "address", kTestDeviceIndex, Technology::kWifi));
404}
405
406TEST_F(DeviceInfoTest, CreateDeviceTunnelAccepted) {
407 IPAddress address = CreateInterfaceAddress();
408
409 // A VPN device should be offered to VPNProvider.
410 StrictMock<MockVPNProvider> vpn_provider;
411 EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&vpn_provider));
412 EXPECT_CALL(vpn_provider,
413 OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
414 .WillOnce(Return(true));
415 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
416 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
417 IsIPAddress(address)));
418 EXPECT_CALL(rtnl_handler_, RemoveInterface(_)).Times(0);
419 EXPECT_FALSE(CreateDevice(
420 kTestDeviceName, "address", kTestDeviceIndex, Technology::kTunnel));
421}
422
423TEST_F(DeviceInfoTest, CreateDeviceTunnelRejected) {
424 IPAddress address = CreateInterfaceAddress();
425
426 // A VPN device should be offered to VPNProvider.
427 StrictMock<MockVPNProvider> vpn_provider;
428 EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&vpn_provider));
429 EXPECT_CALL(vpn_provider,
430 OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
431 .WillOnce(Return(false));
432 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
433 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
434 IsIPAddress(address)));
435 // Since the device was rejected by the VPNProvider, DeviceInfo will
436 // remove the interface.
437 EXPECT_CALL(rtnl_handler_, RemoveInterface(kTestDeviceIndex)).Times(1);
438 EXPECT_FALSE(CreateDevice(
439 kTestDeviceName, "address", kTestDeviceIndex, Technology::kTunnel));
440}
441
442TEST_F(DeviceInfoTest, CreateDevicePPP) {
443 IPAddress address = CreateInterfaceAddress();
444
445 // A VPN device should be offered to VPNProvider.
446 StrictMock<MockVPNProvider> vpn_provider;
447 EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&vpn_provider));
448 EXPECT_CALL(vpn_provider,
449 OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
450 .WillOnce(Return(false));
451 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
452 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
453 IsIPAddress(address)));
454 // We do not remove PPP interfaces even if the provider does not accept it.
455 EXPECT_CALL(rtnl_handler_, RemoveInterface(_)).Times(0);
456 EXPECT_FALSE(CreateDevice(
457 kTestDeviceName, "address", kTestDeviceIndex, Technology::kPPP));
458}
459
460TEST_F(DeviceInfoTest, CreateDeviceLoopback) {
461 // A loopback device should be brought up, and nothing else done to it.
462 EXPECT_CALL(routing_table_, FlushRoutes(_)).Times(0);
463 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(_, _)).Times(0);
464 EXPECT_CALL(rtnl_handler_,
465 SetInterfaceFlags(kTestDeviceIndex, IFF_UP, IFF_UP)).Times(1);
466 EXPECT_FALSE(CreateDevice(
467 kTestDeviceName, "address", kTestDeviceIndex, Technology::kLoopback));
468}
469
Paul Stewart050cfc02012-07-06 20:38:54 -0700470TEST_F(DeviceInfoTest, CreateDeviceCDCEthernet) {
471 // A cdc_ether device should be postponed to a task.
472 EXPECT_CALL(manager_, modem_info()).Times(0);
473 EXPECT_CALL(routing_table_, FlushRoutes(_)).Times(0);
474 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(_, _)).Times(0);
475 EXPECT_CALL(dispatcher_,
Paul Stewart1ac4e842012-07-10 12:58:12 -0700476 PostDelayedTask(_, GetDelayedDeviceCreationMilliseconds()));
Paul Stewart050cfc02012-07-06 20:38:54 -0700477 EXPECT_TRUE(GetDelayedDevices().empty());
478 EXPECT_FALSE(CreateDevice(
479 kTestDeviceName, "address", kTestDeviceIndex, Technology::kCDCEthernet));
480 EXPECT_FALSE(GetDelayedDevices().empty());
481 EXPECT_EQ(1, GetDelayedDevices().size());
482 EXPECT_EQ(kTestDeviceIndex, *GetDelayedDevices().begin());
483}
484
Paul Stewart8c116a92012-05-02 18:30:03 -0700485TEST_F(DeviceInfoTest, CreateDeviceUnknown) {
486 IPAddress address = CreateInterfaceAddress();
487
488 // An unknown (blacklisted, unhandled, etc) device won't be flushed or
489 // registered.
490 EXPECT_CALL(routing_table_, FlushRoutes(_)).Times(0);
491 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(_, _)).Times(0);
492 EXPECT_TRUE(CreateDevice(
493 kTestDeviceName, "address", kTestDeviceIndex, Technology::kUnknown));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700494}
495
mukesh agrawal8f317b62011-07-15 11:53:23 -0700496TEST_F(DeviceInfoTest, DeviceBlackList) {
497 device_info_.AddDeviceToBlackList(kTestDeviceName);
Paul Stewart9a908082011-08-31 12:18:48 -0700498 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
Darin Petkove6193c02011-08-11 12:42:40 -0700499 SendMessageToDeviceInfo(*message);
mukesh agrawal8f317b62011-07-15 11:53:23 -0700500
Darin Petkove6193c02011-08-11 12:42:40 -0700501 DeviceRefPtr device = device_info_.GetDevice(kTestDeviceIndex);
502 ASSERT_TRUE(device.get());
Joshua Krollda798622012-06-05 12:30:48 -0700503 EXPECT_TRUE(device->technology() == Technology::kBlacklisted);
mukesh agrawal8f317b62011-07-15 11:53:23 -0700504}
505
Paul Stewart9a908082011-08-31 12:18:48 -0700506TEST_F(DeviceInfoTest, DeviceAddressList) {
Paul Stewart9a908082011-08-31 12:18:48 -0700507 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
508 SendMessageToDeviceInfo(*message);
509
510 vector<DeviceInfo::AddressData> addresses;
511 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
512 EXPECT_TRUE(addresses.empty());
513
514 // Add an address to the device address list
Paul Stewart7355ce12011-09-02 10:47:01 -0700515 IPAddress ip_address0(IPAddress::kFamilyIPv4);
Paul Stewart9a908082011-08-31 12:18:48 -0700516 EXPECT_TRUE(ip_address0.SetAddressFromString(kTestIPAddress0));
517 ip_address0.set_prefix(kTestIPAddressPrefix0);
518 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address0, 0, 0));
519 SendMessageToDeviceInfo(*message);
520 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
521 EXPECT_EQ(1, addresses.size());
522 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
523
524 // Re-adding the same address shouldn't cause the address list to change
525 SendMessageToDeviceInfo(*message);
526 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
527 EXPECT_EQ(1, addresses.size());
528 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
529
530 // Adding a new address should expand the list
Paul Stewart7355ce12011-09-02 10:47:01 -0700531 IPAddress ip_address1(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700532 EXPECT_TRUE(ip_address1.SetAddressFromString(kTestIPAddress1));
533 ip_address1.set_prefix(kTestIPAddressPrefix1);
534 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address1, 0, 0));
535 SendMessageToDeviceInfo(*message);
536 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
537 EXPECT_EQ(2, addresses.size());
538 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
539 EXPECT_TRUE(ip_address1.Equals(addresses[1].address));
540
541 // Deleting an address should reduce the list
542 message.reset(BuildAddressMessage(RTNLMessage::kModeDelete,
543 ip_address0,
544 0,
545 0));
546 SendMessageToDeviceInfo(*message);
547 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
548 EXPECT_EQ(1, addresses.size());
549 EXPECT_TRUE(ip_address1.Equals(addresses[0].address));
550
551 // Delete last item
552 message.reset(BuildAddressMessage(RTNLMessage::kModeDelete,
553 ip_address1,
554 0,
555 0));
556 SendMessageToDeviceInfo(*message);
557 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
558 EXPECT_TRUE(addresses.empty());
559
560 // Delete device
561 message.reset(BuildLinkMessage(RTNLMessage::kModeDelete));
Paul Stewart8c116a92012-05-02 18:30:03 -0700562 EXPECT_CALL(manager_, DeregisterDevice(_)).Times(1);
Paul Stewart9a908082011-08-31 12:18:48 -0700563 SendMessageToDeviceInfo(*message);
564
565 // Should be able to handle message for interface that doesn't exist
566 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address0, 0, 0));
567 SendMessageToDeviceInfo(*message);
568 EXPECT_FALSE(device_info_.GetDevice(kTestDeviceIndex).get());
Paul Stewart9a908082011-08-31 12:18:48 -0700569}
570
571TEST_F(DeviceInfoTest, FlushAddressList) {
Paul Stewart9a908082011-08-31 12:18:48 -0700572 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
573 SendMessageToDeviceInfo(*message);
574
Paul Stewart7355ce12011-09-02 10:47:01 -0700575 IPAddress address1(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700576 EXPECT_TRUE(address1.SetAddressFromString(kTestIPAddress1));
577 address1.set_prefix(kTestIPAddressPrefix1);
578 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
579 address1,
580 0,
581 RT_SCOPE_UNIVERSE));
582 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700583 IPAddress address2(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700584 EXPECT_TRUE(address2.SetAddressFromString(kTestIPAddress2));
585 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
586 address2,
587 IFA_F_TEMPORARY,
588 RT_SCOPE_UNIVERSE));
589 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700590 IPAddress address3(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700591 EXPECT_TRUE(address3.SetAddressFromString(kTestIPAddress3));
592 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
593 address3,
594 0,
595 RT_SCOPE_LINK));
596 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700597 IPAddress address4(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700598 EXPECT_TRUE(address4.SetAddressFromString(kTestIPAddress4));
599 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
600 address4,
601 IFA_F_PERMANENT,
602 RT_SCOPE_UNIVERSE));
603 SendMessageToDeviceInfo(*message);
604
605 // DeviceInfo now has 4 addresses associated with it, but only two of
606 // them are valid for flush.
607 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
608 IsIPAddress(address1)));
609 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
610 IsIPAddress(address2)));
611 device_info_.FlushAddresses(kTestDeviceIndex);
Paul Stewart9a908082011-08-31 12:18:48 -0700612}
613
Paul Stewart05a42c22012-08-02 16:47:21 -0700614TEST_F(DeviceInfoTest, HasOtherAddress) {
615 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
616 SendMessageToDeviceInfo(*message);
617
618 IPAddress address0(IPAddress::kFamilyIPv4);
619 EXPECT_TRUE(address0.SetAddressFromString(kTestIPAddress0));
620
621 // There are no addresses on this interface.
622 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address0));
623
624 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
625 address0,
626 0,
627 RT_SCOPE_UNIVERSE));
628 SendMessageToDeviceInfo(*message);
629
630 IPAddress address1(IPAddress::kFamilyIPv6);
631 EXPECT_TRUE(address1.SetAddressFromString(kTestIPAddress1));
632 address1.set_prefix(kTestIPAddressPrefix1);
633 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
634 address1,
635 0,
636 RT_SCOPE_LINK));
637 SendMessageToDeviceInfo(*message);
638
639 IPAddress address2(IPAddress::kFamilyIPv6);
640 EXPECT_TRUE(address2.SetAddressFromString(kTestIPAddress2));
641 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
642 address2,
643 IFA_F_TEMPORARY,
644 RT_SCOPE_UNIVERSE));
645 SendMessageToDeviceInfo(*message);
646
647 IPAddress address3(IPAddress::kFamilyIPv6);
648 EXPECT_TRUE(address3.SetAddressFromString(kTestIPAddress3));
649
650 // The only IPv6 addresses on this interface are either flagged as
651 // temporary, or they are not universally scoped.
652 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address3));
653
654
655 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
656 address3,
657 0,
658 RT_SCOPE_UNIVERSE));
659 SendMessageToDeviceInfo(*message);
660
661 // address0 is on this interface.
662 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address0));
663 // address1 is on this interface.
664 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address1));
665 // address2 is on this interface.
666 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address2));
667 // address3 is on this interface.
668 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address3));
669
670 IPAddress address4(IPAddress::kFamilyIPv6);
671 EXPECT_TRUE(address4.SetAddressFromString(kTestIPAddress4));
672
673 // address4 is not on this interface, but address3 is, and is a qualified
674 // IPv6 address.
675 EXPECT_TRUE(device_info_.HasOtherAddress(kTestDeviceIndex, address4));
676
677 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
678 address4,
679 IFA_F_PERMANENT,
680 RT_SCOPE_UNIVERSE));
681 SendMessageToDeviceInfo(*message);
682
683 // address4 is now on this interface.
684 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address4));
685
686 IPAddress address5(IPAddress::kFamilyIPv4);
687 EXPECT_TRUE(address5.SetAddressFromString(kTestIPAddress5));
688 // address5 is not on this interface, but address0 is.
689 EXPECT_TRUE(device_info_.HasOtherAddress(kTestDeviceIndex, address5));
690
691 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
692 address5,
693 IFA_F_PERMANENT,
694 RT_SCOPE_UNIVERSE));
695 SendMessageToDeviceInfo(*message);
696
697 // address5 is now on this interface.
698 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address5));
699}
700
Thieu Leb27beee2012-04-20 09:19:06 -0700701TEST_F(DeviceInfoTest, HasSubdir) {
Thieu Le8f1c8352012-04-16 11:02:12 -0700702 ScopedTempDir temp_dir;
703 EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
Thieu Leb27beee2012-04-20 09:19:06 -0700704 EXPECT_TRUE(file_util::CreateDirectory(temp_dir.path().Append("child1")));
705 FilePath child2 = temp_dir.path().Append("child2");
706 EXPECT_TRUE(file_util::CreateDirectory(child2));
707 FilePath grandchild = child2.Append("grandchild");
Thieu Le8f1c8352012-04-16 11:02:12 -0700708 EXPECT_TRUE(file_util::CreateDirectory(grandchild));
709 EXPECT_TRUE(file_util::CreateDirectory(grandchild.Append("greatgrandchild")));
Thieu Leb27beee2012-04-20 09:19:06 -0700710 EXPECT_TRUE(DeviceInfo::HasSubdir(temp_dir.path(),
711 FilePath("grandchild")));
712 EXPECT_TRUE(DeviceInfo::HasSubdir(temp_dir.path(),
713 FilePath("greatgrandchild")));
714 EXPECT_FALSE(DeviceInfo::HasSubdir(temp_dir.path(),
715 FilePath("nonexistent")));
Thieu Le8f1c8352012-04-16 11:02:12 -0700716}
717
Gary Morain41780232012-07-31 15:08:31 -0700718TEST_F(DeviceInfoTest, GetMACAddressFromKernelUnknownDevice) {
719 SetSockets();
720 EXPECT_CALL(*mock_sockets_, Socket(PF_INET, SOCK_DGRAM, 0)).Times(0);
721 ByteString mac_address =
722 device_info_.GetMACAddressFromKernel(kTestDeviceIndex);
723 EXPECT_TRUE(mac_address.IsEmpty());
724}
725
726TEST_F(DeviceInfoTest, GetMACAddressFromKernelUnableToOpenSocket) {
727 SetSockets();
728 EXPECT_CALL(*mock_sockets_, Socket(PF_INET, SOCK_DGRAM, 0))
729 .WillOnce(Return(-1));
730 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
731 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_LOWER_UP, 0));
732 SendMessageToDeviceInfo(*message);
733 EXPECT_TRUE(device_info_.GetDevice(kTestDeviceIndex).get());
734 ByteString mac_address =
735 device_info_.GetMACAddressFromKernel(kTestDeviceIndex);
736 EXPECT_TRUE(mac_address.IsEmpty());
737}
738
739TEST_F(DeviceInfoTest, GetMACAddressFromKernelIoctlFails) {
740 SetSockets();
741 const int kFd = 99;
742 EXPECT_CALL(*mock_sockets_, Socket(PF_INET, SOCK_DGRAM, 0))
743 .WillOnce(Return(kFd));
744 EXPECT_CALL(*mock_sockets_, Ioctl(kFd, SIOCGIFHWADDR, NotNull()))
745 .WillOnce(Return(-1));
746 EXPECT_CALL(*mock_sockets_, Close(kFd));
747
748 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
749 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_LOWER_UP, 0));
750 SendMessageToDeviceInfo(*message);
751 EXPECT_TRUE(device_info_.GetDevice(kTestDeviceIndex).get());
752
753 ByteString mac_address =
754 device_info_.GetMACAddressFromKernel(kTestDeviceIndex);
755 EXPECT_TRUE(mac_address.IsEmpty());
756}
757
758MATCHER_P2(IfreqEquals, ifindex, ifname, "") {
759 const struct ifreq *const ifr = static_cast<struct ifreq *>(arg);
760 return (ifr != NULL) &&
761 (ifr->ifr_ifindex == ifindex) &&
762 (strcmp(ifname, ifr->ifr_name) == 0);
763}
764
765ACTION_P(SetIfreq, ifr) {
766 struct ifreq *const ifr_arg = static_cast<struct ifreq *>(arg2);
767 *ifr_arg = ifr;
768}
769
770TEST_F(DeviceInfoTest, GetMACAddressFromKernel) {
771 SetSockets();
772 const int kFd = 99;
773 struct ifreq ifr;
Han Shenfc349252012-08-30 11:36:04 -0700774 static uint8_t kMacAddress[] = {0x00, 0x01, 0x02, 0xaa, 0xbb, 0xcc};
Gary Morain41780232012-07-31 15:08:31 -0700775 memcpy(ifr.ifr_hwaddr.sa_data, kMacAddress, sizeof(kMacAddress));
776 EXPECT_CALL(*mock_sockets_, Socket(PF_INET, SOCK_DGRAM, 0))
777 .WillOnce(Return(kFd));
778 EXPECT_CALL(*mock_sockets_,
779 Ioctl(kFd, SIOCGIFHWADDR,
780 IfreqEquals(kTestDeviceIndex, kTestDeviceName)))
781 .WillOnce(DoAll(SetIfreq(ifr), Return(0)));
782 EXPECT_CALL(*mock_sockets_, Close(kFd));
783
784 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
785 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_LOWER_UP, 0));
786 SendMessageToDeviceInfo(*message);
787 EXPECT_TRUE(device_info_.GetDevice(kTestDeviceIndex).get());
788
789 ByteString mac_address =
790 device_info_.GetMACAddressFromKernel(kTestDeviceIndex);
791 EXPECT_THAT(kMacAddress,
792 ElementsAreArray(mac_address.GetData(), sizeof(kMacAddress)));
793}
794
Paul Stewartca876ee2012-04-21 08:55:58 -0700795class DeviceInfoTechnologyTest : public DeviceInfoTest {
796 public:
Jason Glasgowabc54032012-04-20 16:08:32 -0400797 DeviceInfoTechnologyTest()
798 : DeviceInfoTest(),
799 test_device_name_(kTestDeviceName) {}
Paul Stewartca876ee2012-04-21 08:55:58 -0700800 virtual ~DeviceInfoTechnologyTest() {}
801
802 virtual void SetUp() {
803 temp_dir_.CreateUniqueTempDir();
804 device_info_root_ = temp_dir_.path().Append("sys/class/net");
805 device_info_.device_info_root_ = device_info_root_;
806 // Most tests require that the uevent file exist.
807 CreateInfoFile("uevent", "xxx");
808 }
809
810 Technology::Identifier GetDeviceTechnology() {
Jason Glasgowabc54032012-04-20 16:08:32 -0400811 return device_info_.GetDeviceTechnology(test_device_name_);
Paul Stewartca876ee2012-04-21 08:55:58 -0700812 }
813 FilePath GetInfoPath(const string &name);
814 void CreateInfoFile(const string &name, const string &contents);
815 void CreateInfoSymLink(const string &name, const string &contents);
Jason Glasgowabc54032012-04-20 16:08:32 -0400816 void SetDeviceName(const string &name) {
817 test_device_name_ = name;
818 SetUp();
819 }
Paul Stewartca876ee2012-04-21 08:55:58 -0700820
821 protected:
822 ScopedTempDir temp_dir_;
823 FilePath device_info_root_;
Jason Glasgowabc54032012-04-20 16:08:32 -0400824 string test_device_name_;
Paul Stewartca876ee2012-04-21 08:55:58 -0700825};
826
827FilePath DeviceInfoTechnologyTest::GetInfoPath(const string &name) {
Jason Glasgowabc54032012-04-20 16:08:32 -0400828 return device_info_root_.Append(test_device_name_).Append(name);
Paul Stewartca876ee2012-04-21 08:55:58 -0700829}
830
831void DeviceInfoTechnologyTest::CreateInfoFile(const string &name,
832 const string &contents) {
833 FilePath info_path = GetInfoPath(name);
834 EXPECT_TRUE(file_util::CreateDirectory(info_path.DirName()));
835 string contents_newline(contents + "\n");
836 EXPECT_TRUE(file_util::WriteFile(info_path, contents_newline.c_str(),
837 contents_newline.size()));
838}
839
840void DeviceInfoTechnologyTest::CreateInfoSymLink(const string &name,
841 const string &contents) {
842 FilePath info_path = GetInfoPath(name);
Paul Stewartca876ee2012-04-21 08:55:58 -0700843 EXPECT_TRUE(file_util::CreateDirectory(info_path.DirName()));
844 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath(contents), info_path));
845}
846
847TEST_F(DeviceInfoTechnologyTest, Unknown) {
848 EXPECT_EQ(Technology::kUnknown, GetDeviceTechnology());
849 // Should still be unknown even without a uevent file.
850 EXPECT_TRUE(file_util::Delete(GetInfoPath("uevent"), FALSE));
851 EXPECT_EQ(Technology::kUnknown, GetDeviceTechnology());
852}
853
854TEST_F(DeviceInfoTechnologyTest, Loopback) {
855 CreateInfoFile("type", base::IntToString(ARPHRD_LOOPBACK));
856 EXPECT_EQ(Technology::kLoopback, GetDeviceTechnology());
857}
858
859TEST_F(DeviceInfoTechnologyTest, PPP) {
860 CreateInfoFile("type", base::IntToString(ARPHRD_PPP));
861 EXPECT_EQ(Technology::kPPP, GetDeviceTechnology());
862}
863
864TEST_F(DeviceInfoTechnologyTest, Tunnel) {
865 CreateInfoFile("tun_flags", base::IntToString(IFF_TUN));
866 EXPECT_EQ(Technology::kTunnel, GetDeviceTechnology());
867}
868
869TEST_F(DeviceInfoTechnologyTest, WiFi) {
870 CreateInfoFile("uevent", "DEVTYPE=wlan");
871 EXPECT_EQ(Technology::kWifi, GetDeviceTechnology());
872 CreateInfoFile("uevent", "foo\nDEVTYPE=wlan");
873 EXPECT_EQ(Technology::kWifi, GetDeviceTechnology());
874 CreateInfoFile("type", base::IntToString(ARPHRD_IEEE80211_RADIOTAP));
875 EXPECT_EQ(Technology::kWiFiMonitor, GetDeviceTechnology());
876}
877
878TEST_F(DeviceInfoTechnologyTest, Ethernet) {
879 CreateInfoSymLink("device/driver", "xxx");
880 EXPECT_EQ(Technology::kEthernet, GetDeviceTechnology());
881}
882
Darin Petkove4b27022012-05-16 13:28:50 +0200883TEST_F(DeviceInfoTechnologyTest, WiMax) {
884 CreateInfoSymLink("device/driver", "gdm_wimax");
885 EXPECT_EQ(Technology::kWiMax, GetDeviceTechnology());
886}
887
Paul Stewartca876ee2012-04-21 08:55:58 -0700888TEST_F(DeviceInfoTechnologyTest, CellularGobi1) {
889 CreateInfoSymLink("device/driver", "blah/foo/gobi");
890 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
891}
892
893TEST_F(DeviceInfoTechnologyTest, CellularGobi2) {
894 CreateInfoSymLink("device/driver", "../GobiNet");
895 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
896}
897
898TEST_F(DeviceInfoTechnologyTest, QCUSB) {
899 CreateInfoSymLink("device/driver", "QCUSBNet2k");
900 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
901}
902
Ben Chan226d46a2012-10-11 00:22:17 -0700903TEST_F(DeviceInfoTechnologyTest, CellularQmiWwan) {
904 CreateInfoSymLink("device/driver", "qmi_wwan");
905 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
906}
907
Paul Stewartca876ee2012-04-21 08:55:58 -0700908// Modem with absolute driver path with top-level tty file:
909// /sys/class/net/dev0/device -> /sys/devices/virtual/0/00
910// /sys/devices/virtual/0/00/driver -> /drivers/cdc_ether
911// /sys/devices/virtual/0/01/tty [empty directory]
912TEST_F(DeviceInfoTechnologyTest, CDCEtherModem1) {
913 FilePath device_root(temp_dir_.path().Append("sys/devices/virtual/0"));
914 FilePath device_path(device_root.Append("00"));
915 EXPECT_TRUE(file_util::CreateDirectory(device_path));
916 CreateInfoSymLink("device", device_path.value());
917 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
918 device_path.Append("driver")));
919 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/tty")));
920 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
921}
922
923// Modem with relative driver path with top-level tty file.
924// /sys/class/net/dev0/device -> ../../../device_dir/0/00
925// /sys/device_dir/0/00/driver -> /drivers/cdc_ether
926// /sys/device_dir/0/01/tty [empty directory]
927TEST_F(DeviceInfoTechnologyTest, CDCEtherModem2) {
928 CreateInfoSymLink("device", "../../../device_dir/0/00");
929 FilePath device_root(temp_dir_.path().Append("sys/device_dir/0"));
930 FilePath device_path(device_root.Append("00"));
931 EXPECT_TRUE(file_util::CreateDirectory(device_path));
932 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
933 device_path.Append("driver")));
934 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/tty")));
935 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
936}
937
938// Modem with relative driver path with lower-level tty file.
939// /sys/class/net/dev0/device -> ../../../device_dir/0/00
940// /sys/device_dir/0/00/driver -> /drivers/cdc_ether
941// /sys/device_dir/0/01/yyy/tty [empty directory]
942TEST_F(DeviceInfoTechnologyTest, CDCEtherModem3) {
943 CreateInfoSymLink("device", "../../../device_dir/0/00");
944 FilePath device_root(temp_dir_.path().Append("sys/device_dir/0"));
945 FilePath device_path(device_root.Append("00"));
946 EXPECT_TRUE(file_util::CreateDirectory(device_path));
947 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
948 device_path.Append("driver")));
949 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/yyy/tty")));
950 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
951}
952
953TEST_F(DeviceInfoTechnologyTest, CDCEtherNonModem) {
954 CreateInfoSymLink("device", "device_dir");
955 CreateInfoSymLink("device_dir/driver", "cdc_ether");
Paul Stewart050cfc02012-07-06 20:38:54 -0700956 EXPECT_EQ(Technology::kCDCEthernet, GetDeviceTechnology());
Paul Stewartca876ee2012-04-21 08:55:58 -0700957}
958
Jason Glasgowabc54032012-04-20 16:08:32 -0400959TEST_F(DeviceInfoTechnologyTest, PseudoModem) {
960 SetDeviceName("pseudomodem");
961 CreateInfoSymLink("device", "device_dir");
962 CreateInfoSymLink("device_dir/driver", "cdc_ether");
963 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
964
965 SetDeviceName("pseudomodem9");
966 CreateInfoSymLink("device", "device_dir");
967 CreateInfoSymLink("device_dir/driver", "cdc_ether");
968 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
969}
970
Paul Stewart050cfc02012-07-06 20:38:54 -0700971class DeviceInfoForDelayedCreationTest : public DeviceInfo {
972 public:
973 DeviceInfoForDelayedCreationTest(ControlInterface *control_interface,
974 EventDispatcher *dispatcher,
975 Metrics *metrics,
976 Manager *manager)
977 : DeviceInfo(control_interface, dispatcher, metrics, manager) {}
978 MOCK_METHOD4(CreateDevice, DeviceRefPtr(const std::string &link_name,
979 const std::string &address,
980 int interface_index,
981 Technology::Identifier technology));
982 MOCK_METHOD1(GetDeviceTechnology,
983 Technology::Identifier(const string &iface_name));
984};
985
986class DeviceInfoDelayedCreationTest : public DeviceInfoTest {
987 public:
988 DeviceInfoDelayedCreationTest()
989 : DeviceInfoTest(),
990 test_device_info_(
991 &control_interface_, &dispatcher_, &metrics_, &manager_) {}
992 virtual ~DeviceInfoDelayedCreationTest() {}
993
994 virtual std::set<int> &GetDelayedDevices() {
995 return test_device_info_.delayed_devices_;
996 }
997
998 void DelayedDeviceCreationTask() {
999 test_device_info_.DelayedDeviceCreationTask();
1000 }
1001
1002 void AddDelayedDevice() {
1003 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
1004 EXPECT_CALL(test_device_info_, GetDeviceTechnology(kTestDeviceName))
1005 .WillOnce(Return(Technology::kCDCEthernet));
1006 EXPECT_CALL(test_device_info_, CreateDevice(
1007 kTestDeviceName, _, kTestDeviceIndex, Technology::kCDCEthernet))
1008 .WillOnce(Return(DeviceRefPtr()));
1009 test_device_info_.AddLinkMsgHandler(*message);
1010 Mock::VerifyAndClearExpectations(&test_device_info_);
1011 // We need to insert the device index ourselves since we have mocked
1012 // out CreateDevice. This insertion is tested in CreateDeviceCDCEthernet
1013 // above.
1014 GetDelayedDevices().insert(kTestDeviceIndex);
1015 }
1016
1017 protected:
1018 DeviceInfoForDelayedCreationTest test_device_info_;
1019};
1020
1021TEST_F(DeviceInfoDelayedCreationTest, NoDevices) {
1022 EXPECT_TRUE(GetDelayedDevices().empty());
1023 EXPECT_CALL(test_device_info_, GetDeviceTechnology(_)).Times(0);
1024 DelayedDeviceCreationTask();
1025}
1026
1027TEST_F(DeviceInfoDelayedCreationTest, EthernetDevice) {
1028 AddDelayedDevice();
1029 EXPECT_CALL(test_device_info_, GetDeviceTechnology(_))
1030 .WillOnce(Return(Technology::kCDCEthernet));
1031 EXPECT_CALL(test_device_info_, CreateDevice(
1032 kTestDeviceName, _, kTestDeviceIndex, Technology::kEthernet))
1033 .WillOnce(Return(DeviceRefPtr()));
1034 DelayedDeviceCreationTask();
1035 EXPECT_TRUE(GetDelayedDevices().empty());
1036}
1037
1038TEST_F(DeviceInfoDelayedCreationTest, CellularDevice) {
1039 AddDelayedDevice();
1040 EXPECT_CALL(test_device_info_, GetDeviceTechnology(_))
1041 .WillOnce(Return(Technology::kCellular));
1042 EXPECT_CALL(test_device_info_, CreateDevice(
1043 kTestDeviceName, _, kTestDeviceIndex, Technology::kCellular))
1044 .WillOnce(Return(DeviceRefPtr()));
1045 DelayedDeviceCreationTask();
1046 EXPECT_TRUE(GetDelayedDevices().empty());
1047}
1048
Chris Masone9be4a9d2011-05-16 15:44:09 -07001049} // namespace shill