blob: 985b65d3f2d17ca71e2017971b373416bcd75e3e [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 <gmock/gmock.h>
Ben Chan5086b972013-01-15 21:51:38 -080023#include <gtest/gtest.h>
Chris Masone9be4a9d2011-05-16 15:44:09 -070024
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"
Ben Chan5086b972013-01-15 21:51:38 -080029#include "shill/mock_device.h"
Darin Petkovafa6fc42011-06-21 16:21:08 -070030#include "shill/mock_glib.h"
Chris Masone2ae797d2011-08-23 20:41:00 -070031#include "shill/mock_manager.h"
Thieu Le3426c8f2012-01-11 17:35:11 -080032#include "shill/mock_metrics.h"
Paul Stewart8c116a92012-05-02 18:30:03 -070033#include "shill/mock_modem_info.h"
34#include "shill/mock_routing_table.h"
Paul Stewart9a908082011-08-31 12:18:48 -070035#include "shill/mock_rtnl_handler.h"
Darin Petkov633ac6f2011-07-08 13:56:13 -070036#include "shill/mock_sockets.h"
Paul Stewart8c116a92012-05-02 18:30:03 -070037#include "shill/mock_vpn_provider.h"
Darin Petkove4b27022012-05-16 13:28:50 +020038#include "shill/mock_wimax_provider.h"
Chris Masone2aa97072011-08-09 17:35:08 -070039#include "shill/rtnl_message.h"
Darin Petkovc63dcf02012-05-24 11:51:43 +020040#include "shill/wimax.h"
Chris Masone9be4a9d2011-05-16 15:44:09 -070041
Eric Shienbrood3e20a232012-02-16 11:35:56 -050042using base::Callback;
Darin Petkove6193c02011-08-11 12:42:40 -070043using std::map;
Ben Chan5086b972013-01-15 21:51:38 -080044using std::set;
Darin Petkov633ac6f2011-07-08 13:56:13 -070045using std::string;
Paul Stewart9a908082011-08-31 12:18:48 -070046using std::vector;
Darin Petkov633ac6f2011-07-08 13:56:13 -070047using testing::_;
Ben Chan5086b972013-01-15 21:51:38 -080048using testing::ContainerEq;
Gary Morain41780232012-07-31 15:08:31 -070049using testing::DoAll;
50using testing::ElementsAreArray;
Paul Stewart8c116a92012-05-02 18:30:03 -070051using testing::Mock;
Gary Morain41780232012-07-31 15:08:31 -070052using testing::NotNull;
Darin Petkov633ac6f2011-07-08 13:56:13 -070053using testing::Return;
Paul Stewart9a908082011-08-31 12:18:48 -070054using testing::StrictMock;
Darin Petkov633ac6f2011-07-08 13:56:13 -070055using testing::Test;
56
Chris Masone9be4a9d2011-05-16 15:44:09 -070057namespace shill {
Darin Petkov633ac6f2011-07-08 13:56:13 -070058
Paul Stewart050cfc02012-07-06 20:38:54 -070059class TestEventDispatcherForDeviceInfo : public EventDispatcher {
Darin Petkov633ac6f2011-07-08 13:56:13 -070060 public:
Paul Stewart26b327e2011-10-19 11:38:09 -070061 virtual IOHandler *CreateInputHandler(
mukesh agrawal1830fa12011-09-26 14:31:40 -070062 int /*fd*/,
Paul Stewart5f06a0e2012-12-20 11:11:33 -080063 const IOHandler::InputCallback &/*input_callback*/,
64 const IOHandler::ErrorCallback &/*error_callback*/) {
Darin Petkov633ac6f2011-07-08 13:56:13 -070065 return NULL;
66 }
Paul Stewart050cfc02012-07-06 20:38:54 -070067 MOCK_METHOD2(PostDelayedTask, bool(const base::Closure &task,
68 int64 delay_ms));
Darin Petkov633ac6f2011-07-08 13:56:13 -070069};
Chris Masone9be4a9d2011-05-16 15:44:09 -070070
71class DeviceInfoTest : public Test {
72 public:
73 DeviceInfoTest()
Thieu Le3426c8f2012-01-11 17:35:11 -080074 : manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
75 device_info_(&control_interface_, &dispatcher_, &metrics_, &manager_) {
Chris Masone9be4a9d2011-05-16 15:44:09 -070076 }
Paul Stewartca876ee2012-04-21 08:55:58 -070077 virtual ~DeviceInfoTest() {}
Darin Petkov633ac6f2011-07-08 13:56:13 -070078
Paul Stewart9a908082011-08-31 12:18:48 -070079 virtual void SetUp() {
80 device_info_.rtnl_handler_ = &rtnl_handler_;
Paul Stewart8c116a92012-05-02 18:30:03 -070081 device_info_.routing_table_ = &routing_table_;
Paul Stewart9a908082011-08-31 12:18:48 -070082 }
83
Paul Stewart8c116a92012-05-02 18:30:03 -070084 IPAddress CreateInterfaceAddress() {
85 // Create an IP address entry (as if left-over from a previous connection
86 // manager).
87 IPAddress address(IPAddress::kFamilyIPv4);
88 EXPECT_TRUE(address.SetAddressFromString(kTestIPAddress0));
89 address.set_prefix(kTestIPAddressPrefix0);
90 vector<DeviceInfo::AddressData> &addresses =
91 device_info_.infos_[kTestDeviceIndex].ip_addresses;
92 addresses.push_back(DeviceInfo::AddressData(address, 0, RT_SCOPE_UNIVERSE));
93 EXPECT_EQ(1, addresses.size());
94 return address;
95 }
96
97 DeviceRefPtr CreateDevice(const std::string &link_name,
98 const std::string &address,
99 int interface_index,
100 Technology::Identifier technology) {
101 return device_info_.CreateDevice(link_name, address, interface_index,
102 technology);
103 }
104
Paul Stewart050cfc02012-07-06 20:38:54 -0700105 virtual std::set<int> &GetDelayedDevices() {
106 return device_info_.delayed_devices_;
107 }
108
Paul Stewart1ac4e842012-07-10 12:58:12 -0700109 int GetDelayedDeviceCreationMilliseconds() {
Paul Stewart050cfc02012-07-06 20:38:54 -0700110 return DeviceInfo::kDelayedDeviceCreationSeconds * 1000;
111 }
Paul Stewart8c116a92012-05-02 18:30:03 -0700112
Paul Stewart1ac4e842012-07-10 12:58:12 -0700113 int GetRequestLinkStatisticsIntervalMilliseconds() {
114 return DeviceInfo::kRequestLinkStatisticsIntervalSeconds * 1000;
115 }
116
Gary Morain41780232012-07-31 15:08:31 -0700117 void SetSockets() {
118 mock_sockets_ = new MockSockets();
119 device_info_.set_sockets(mock_sockets_);
120 }
121
Paul Stewarta3c56f92011-05-26 07:08:52 -0700122 protected:
Chris Masoneb2e326b2011-07-12 13:28:51 -0700123 static const int kTestDeviceIndex;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700124 static const char kTestDeviceName[];
Han Shenfc349252012-08-30 11:36:04 -0700125 static const uint8_t kTestMACAddress[];
Paul Stewart9a908082011-08-31 12:18:48 -0700126 static const char kTestIPAddress0[];
127 static const int kTestIPAddressPrefix0;
128 static const char kTestIPAddress1[];
129 static const int kTestIPAddressPrefix1;
130 static const char kTestIPAddress2[];
131 static const char kTestIPAddress3[];
132 static const char kTestIPAddress4[];
Paul Stewart05a42c22012-08-02 16:47:21 -0700133 static const char kTestIPAddress5[];
Paul Stewart1ac4e842012-07-10 12:58:12 -0700134 static const int kReceiveByteCount;
135 static const int kTransmitByteCount;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700136
Paul Stewart9a908082011-08-31 12:18:48 -0700137 RTNLMessage *BuildLinkMessage(RTNLMessage::Mode mode);
Paul Stewarte81eb702012-04-11 15:04:53 -0700138 RTNLMessage *BuildLinkMessageWithInterfaceName(RTNLMessage::Mode mode,
139 const string &interface_name);
Paul Stewart9a908082011-08-31 12:18:48 -0700140 RTNLMessage *BuildAddressMessage(RTNLMessage::Mode mode,
141 const IPAddress &address,
142 unsigned char flags,
143 unsigned char scope);
Chris Masone2aa97072011-08-09 17:35:08 -0700144 void SendMessageToDeviceInfo(const RTNLMessage &message);
Darin Petkov633ac6f2011-07-08 13:56:13 -0700145
Darin Petkovafa6fc42011-06-21 16:21:08 -0700146 MockGLib glib_;
Chris Masone46eaaf52011-05-24 13:08:30 -0700147 MockControl control_interface_;
Thieu Le3426c8f2012-01-11 17:35:11 -0800148 MockMetrics metrics_;
Paul Stewart9a908082011-08-31 12:18:48 -0700149 StrictMock<MockManager> manager_;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700150 DeviceInfo device_info_;
Paul Stewart050cfc02012-07-06 20:38:54 -0700151 TestEventDispatcherForDeviceInfo dispatcher_;
Paul Stewart8c116a92012-05-02 18:30:03 -0700152 MockRoutingTable routing_table_;
Paul Stewart9a908082011-08-31 12:18:48 -0700153 StrictMock<MockRTNLHandler> rtnl_handler_;
Gary Morain41780232012-07-31 15:08:31 -0700154 MockSockets *mock_sockets_; // Owned by DeviceInfo.
Chris Masone9be4a9d2011-05-16 15:44:09 -0700155};
156
Chris Masoneb2e326b2011-07-12 13:28:51 -0700157const int DeviceInfoTest::kTestDeviceIndex = 123456;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700158const char DeviceInfoTest::kTestDeviceName[] = "test-device";
Han Shenfc349252012-08-30 11:36:04 -0700159const uint8_t DeviceInfoTest::kTestMACAddress[] = {
160 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
Paul Stewart9a908082011-08-31 12:18:48 -0700161const char DeviceInfoTest::kTestIPAddress0[] = "192.168.1.1";
162const int DeviceInfoTest::kTestIPAddressPrefix0 = 24;
163const char DeviceInfoTest::kTestIPAddress1[] = "fe80::1aa9:5ff:abcd:1234";
164const int DeviceInfoTest::kTestIPAddressPrefix1 = 64;
165const char DeviceInfoTest::kTestIPAddress2[] = "fe80::1aa9:5ff:abcd:1235";
166const char DeviceInfoTest::kTestIPAddress3[] = "fe80::1aa9:5ff:abcd:1236";
167const char DeviceInfoTest::kTestIPAddress4[] = "fe80::1aa9:5ff:abcd:1237";
Paul Stewart05a42c22012-08-02 16:47:21 -0700168const char DeviceInfoTest::kTestIPAddress5[] = "192.168.1.2";
Paul Stewart1ac4e842012-07-10 12:58:12 -0700169const int DeviceInfoTest::kReceiveByteCount = 1234;
170const int DeviceInfoTest::kTransmitByteCount = 5678;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700171
Paul Stewarte81eb702012-04-11 15:04:53 -0700172RTNLMessage *DeviceInfoTest::BuildLinkMessageWithInterfaceName(
173 RTNLMessage::Mode mode, const string &interface_name) {
Paul Stewart9a908082011-08-31 12:18:48 -0700174 RTNLMessage *message = new RTNLMessage(
175 RTNLMessage::kTypeLink,
176 mode,
177 0,
178 0,
179 0,
180 kTestDeviceIndex,
Paul Stewart7355ce12011-09-02 10:47:01 -0700181 IPAddress::kFamilyIPv4);
Chris Masone2aa97072011-08-09 17:35:08 -0700182 message->SetAttribute(static_cast<uint16>(IFLA_IFNAME),
Paul Stewarte81eb702012-04-11 15:04:53 -0700183 ByteString(interface_name, true));
Paul Stewart9a908082011-08-31 12:18:48 -0700184 ByteString test_address(kTestMACAddress, sizeof(kTestMACAddress));
Chris Masone626719f2011-08-18 16:58:48 -0700185 message->SetAttribute(IFLA_ADDRESS, test_address);
Chris Masone2aa97072011-08-09 17:35:08 -0700186 return message;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700187}
188
Paul Stewarte81eb702012-04-11 15:04:53 -0700189RTNLMessage *DeviceInfoTest::BuildLinkMessage(RTNLMessage::Mode mode) {
190 return BuildLinkMessageWithInterfaceName(mode, kTestDeviceName);
191}
192
Paul Stewart9a908082011-08-31 12:18:48 -0700193RTNLMessage *DeviceInfoTest::BuildAddressMessage(RTNLMessage::Mode mode,
194 const IPAddress &address,
195 unsigned char flags,
196 unsigned char scope) {
197 RTNLMessage *message = new RTNLMessage(
198 RTNLMessage::kTypeAddress,
199 mode,
200 0,
201 0,
202 0,
203 kTestDeviceIndex,
204 address.family());
205 message->SetAttribute(IFA_ADDRESS, address.address());
206 message->set_address_status(
207 RTNLMessage::AddressStatus(address.prefix(), flags, scope));
208 return message;
209}
210
Chris Masone2aa97072011-08-09 17:35:08 -0700211void DeviceInfoTest::SendMessageToDeviceInfo(const RTNLMessage &message) {
Paul Stewart9a908082011-08-31 12:18:48 -0700212 if (message.type() == RTNLMessage::kTypeLink) {
213 device_info_.LinkMsgHandler(message);
214 } else if (message.type() == RTNLMessage::kTypeAddress) {
215 device_info_.AddressMsgHandler(message);
216 } else {
217 NOTREACHED();
218 }
219}
220
221MATCHER_P(IsIPAddress, address, "") {
222 // NB: IPAddress objects don't support the "==" operator as per style, so
223 // we need a custom matcher.
224 return address.Equals(arg);
Darin Petkov633ac6f2011-07-08 13:56:13 -0700225}
226
Paul Stewart8c116a92012-05-02 18:30:03 -0700227TEST_F(DeviceInfoTest, StartStop) {
228 EXPECT_FALSE(device_info_.link_listener_.get());
229 EXPECT_FALSE(device_info_.address_listener_.get());
230 EXPECT_TRUE(device_info_.infos_.empty());
231
232 EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestLink |
233 RTNLHandler::kRequestAddr));
Paul Stewart1ac4e842012-07-10 12:58:12 -0700234 EXPECT_CALL(dispatcher_, PostDelayedTask(
235 _, GetRequestLinkStatisticsIntervalMilliseconds()));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700236 device_info_.Start();
Paul Stewart8c116a92012-05-02 18:30:03 -0700237 EXPECT_TRUE(device_info_.link_listener_.get());
238 EXPECT_TRUE(device_info_.address_listener_.get());
239 EXPECT_TRUE(device_info_.infos_.empty());
240 Mock::VerifyAndClearExpectations(&rtnl_handler_);
241
242 CreateInterfaceAddress();
243 EXPECT_FALSE(device_info_.infos_.empty());
244
245 device_info_.Stop();
246 EXPECT_FALSE(device_info_.link_listener_.get());
247 EXPECT_FALSE(device_info_.address_listener_.get());
248 EXPECT_TRUE(device_info_.infos_.empty());
249}
250
Paul Stewart1ac4e842012-07-10 12:58:12 -0700251TEST_F(DeviceInfoTest, RequestLinkStatistics) {
252 EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestLink));
253 EXPECT_CALL(dispatcher_, PostDelayedTask(
254 _, GetRequestLinkStatisticsIntervalMilliseconds()));
255 device_info_.RequestLinkStatistics();
256}
257
Paul Stewart8c116a92012-05-02 18:30:03 -0700258TEST_F(DeviceInfoTest, DeviceEnumeration) {
Paul Stewart9a908082011-08-31 12:18:48 -0700259 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
Darin Petkove6193c02011-08-11 12:42:40 -0700260 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_LOWER_UP, 0));
261 EXPECT_FALSE(device_info_.GetDevice(kTestDeviceIndex).get());
Darin Petkovf8046b82012-04-24 16:29:23 +0200262 EXPECT_EQ(-1, device_info_.GetIndex(kTestDeviceName));
Darin Petkove6193c02011-08-11 12:42:40 -0700263 SendMessageToDeviceInfo(*message);
264 EXPECT_TRUE(device_info_.GetDevice(kTestDeviceIndex).get());
265 unsigned int flags = 0;
266 EXPECT_TRUE(device_info_.GetFlags(kTestDeviceIndex, &flags));
267 EXPECT_EQ(IFF_LOWER_UP, flags);
Darin Petkove3e1cfa2011-08-11 13:41:17 -0700268 ByteString address;
Paul Stewart32852962011-08-30 14:06:53 -0700269 EXPECT_TRUE(device_info_.GetMACAddress(kTestDeviceIndex, &address));
Darin Petkove3e1cfa2011-08-11 13:41:17 -0700270 EXPECT_FALSE(address.IsEmpty());
Paul Stewart9a908082011-08-31 12:18:48 -0700271 EXPECT_TRUE(address.Equals(ByteString(kTestMACAddress,
272 sizeof(kTestMACAddress))));
Darin Petkovf8046b82012-04-24 16:29:23 +0200273 EXPECT_EQ(kTestDeviceIndex, device_info_.GetIndex(kTestDeviceName));
Paul Stewarta3c56f92011-05-26 07:08:52 -0700274
Paul Stewart9a908082011-08-31 12:18:48 -0700275 message.reset(BuildLinkMessage(RTNLMessage::kModeAdd));
Darin Petkove6193c02011-08-11 12:42:40 -0700276 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_UP | IFF_RUNNING, 0));
277 SendMessageToDeviceInfo(*message);
278 EXPECT_TRUE(device_info_.GetFlags(kTestDeviceIndex, &flags));
279 EXPECT_EQ(IFF_UP | IFF_RUNNING, flags);
Paul Stewartb50f0b92011-05-16 16:31:42 -0700280
Paul Stewart9a908082011-08-31 12:18:48 -0700281 message.reset(BuildLinkMessage(RTNLMessage::kModeDelete));
Paul Stewart8c116a92012-05-02 18:30:03 -0700282 EXPECT_CALL(manager_, DeregisterDevice(_)).Times(1);
Darin Petkove6193c02011-08-11 12:42:40 -0700283 SendMessageToDeviceInfo(*message);
284 EXPECT_FALSE(device_info_.GetDevice(kTestDeviceIndex).get());
285 EXPECT_FALSE(device_info_.GetFlags(kTestDeviceIndex, NULL));
Darin Petkovf8046b82012-04-24 16:29:23 +0200286 EXPECT_EQ(-1, device_info_.GetIndex(kTestDeviceName));
Paul Stewart8c116a92012-05-02 18:30:03 -0700287}
Paul Stewarta3c56f92011-05-26 07:08:52 -0700288
Ben Chan5086b972013-01-15 21:51:38 -0800289TEST_F(DeviceInfoTest, GetUninitializedTechnologies) {
290 vector<string> technologies = device_info_.GetUninitializedTechnologies();
291 set<string> expected_technologies;
292
293 EXPECT_THAT(set<string>(technologies.begin(), technologies.end()),
294 ContainerEq(expected_technologies));
295
296 device_info_.infos_[0].technology = Technology::kUnknown;
297 EXPECT_THAT(set<string>(technologies.begin(), technologies.end()),
298 ContainerEq(expected_technologies));
299
300 device_info_.infos_[1].technology = Technology::kCellular;
301 technologies = device_info_.GetUninitializedTechnologies();
302 expected_technologies.insert(Technology::NameFromIdentifier(
303 Technology::kCellular));
304 EXPECT_THAT(set<string>(technologies.begin(), technologies.end()),
305 ContainerEq(expected_technologies));
306
307 device_info_.infos_[2].technology = Technology::kWiMax;
308 technologies = device_info_.GetUninitializedTechnologies();
309 expected_technologies.insert(Technology::NameFromIdentifier(
310 Technology::kWiMax));
311 EXPECT_THAT(set<string>(technologies.begin(), technologies.end()),
312 ContainerEq(expected_technologies));
313
314 scoped_refptr<MockDevice> device(new MockDevice(
315 &control_interface_, &dispatcher_, &metrics_, &manager_,
316 "null0", "addr0", 1));
317 device_info_.infos_[1].device = device;
318 technologies = device_info_.GetUninitializedTechnologies();
319 expected_technologies.erase(Technology::NameFromIdentifier(
320 Technology::kCellular));
321 EXPECT_THAT(set<string>(technologies.begin(), technologies.end()),
322 ContainerEq(expected_technologies));
323
324 device_info_.infos_[3].technology = Technology::kCellular;
325 technologies = device_info_.GetUninitializedTechnologies();
326 expected_technologies.insert(Technology::NameFromIdentifier(
327 Technology::kCellular));
328 EXPECT_THAT(set<string>(technologies.begin(), technologies.end()),
329 ContainerEq(expected_technologies));
330}
331
Paul Stewart1ac4e842012-07-10 12:58:12 -0700332TEST_F(DeviceInfoTest, GetByteCounts) {
333 uint64 rx_bytes, tx_bytes;
334 EXPECT_FALSE(device_info_.GetByteCounts(
335 kTestDeviceIndex, &rx_bytes, &tx_bytes));
336
337 // No link statistics in the message.
338 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
339 SendMessageToDeviceInfo(*message);
340 EXPECT_TRUE(device_info_.GetByteCounts(
341 kTestDeviceIndex, &rx_bytes, &tx_bytes));
342 EXPECT_EQ(0, rx_bytes);
343 EXPECT_EQ(0, tx_bytes);
344
345 // Short link statistics message.
346 message.reset(BuildLinkMessage(RTNLMessage::kModeAdd));
347 struct rtnl_link_stats64 stats;
348 memset(&stats, 0, sizeof(stats));
349 stats.rx_bytes = kReceiveByteCount;
350 stats.tx_bytes = kTransmitByteCount;
351 ByteString stats_bytes0(reinterpret_cast<const unsigned char*>(&stats),
352 sizeof(stats) - 1);
353 message->SetAttribute(IFLA_STATS64, stats_bytes0);
354 SendMessageToDeviceInfo(*message);
355 EXPECT_TRUE(device_info_.GetByteCounts(
356 kTestDeviceIndex, &rx_bytes, &tx_bytes));
357 EXPECT_EQ(0, rx_bytes);
358 EXPECT_EQ(0, tx_bytes);
359
360 // Correctly sized link statistics message.
361 message.reset(BuildLinkMessage(RTNLMessage::kModeAdd));
362 ByteString stats_bytes1(reinterpret_cast<const unsigned char*>(&stats),
363 sizeof(stats));
364 message->SetAttribute(IFLA_STATS64, stats_bytes1);
365 SendMessageToDeviceInfo(*message);
366 EXPECT_TRUE(device_info_.GetByteCounts(
367 kTestDeviceIndex, &rx_bytes, &tx_bytes));
368 EXPECT_EQ(kReceiveByteCount, rx_bytes);
369 EXPECT_EQ(kTransmitByteCount, tx_bytes);
370}
371
Paul Stewart8c116a92012-05-02 18:30:03 -0700372TEST_F(DeviceInfoTest, CreateDeviceCellular) {
373 IPAddress address = CreateInterfaceAddress();
374
375 // A cellular device should be offered to ModemInfo.
376 StrictMock<MockModemInfo> modem_info;
377 EXPECT_CALL(manager_, modem_info()).WillOnce(Return(&modem_info));
378 EXPECT_CALL(modem_info, OnDeviceInfoAvailable(kTestDeviceName)).Times(1);
379 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
380 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
381 IsIPAddress(address)));
382 EXPECT_FALSE(CreateDevice(
383 kTestDeviceName, "address", kTestDeviceIndex, Technology::kCellular));
384}
385
Darin Petkove4b27022012-05-16 13:28:50 +0200386TEST_F(DeviceInfoTest, CreateDeviceWiMax) {
387 IPAddress address = CreateInterfaceAddress();
388
389 // A WiMax device should be offered to WiMaxProvider.
390 StrictMock<MockWiMaxProvider> wimax_provider;
391 EXPECT_CALL(manager_, wimax_provider()).WillOnce(Return(&wimax_provider));
392 EXPECT_CALL(wimax_provider, OnDeviceInfoAvailable(kTestDeviceName)).Times(1);
393 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
394 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
395 IsIPAddress(address)));
Ben Chan4b285862012-10-10 22:52:16 -0700396 device_info_.infos_[kTestDeviceIndex].mac_address =
397 ByteString(kTestMACAddress, sizeof(kTestMACAddress));
Darin Petkove4b27022012-05-16 13:28:50 +0200398 EXPECT_FALSE(CreateDevice(
399 kTestDeviceName, "address", kTestDeviceIndex, Technology::kWiMax));
Ben Chan4b285862012-10-10 22:52:16 -0700400 // The MAC address is clear such that it is obtained via
401 // GetMACAddressFromKernel() instead.
402 EXPECT_TRUE(device_info_.infos_[kTestDeviceIndex].mac_address.IsEmpty());
Darin Petkove4b27022012-05-16 13:28:50 +0200403}
404
Paul Stewart8c116a92012-05-02 18:30:03 -0700405TEST_F(DeviceInfoTest, CreateDeviceEthernet) {
406 IPAddress address = CreateInterfaceAddress();
407
408 // An Ethernet device should cause routes and addresses to be flushed.
409 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
410 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
411 IsIPAddress(address)));
412 DeviceRefPtr device = CreateDevice(
413 kTestDeviceName, "address", kTestDeviceIndex, Technology::kEthernet);
414 EXPECT_TRUE(device);
415 Mock::VerifyAndClearExpectations(&routing_table_);
416 Mock::VerifyAndClearExpectations(&rtnl_handler_);
417
418 // The Ethernet device destructor notifies the manager.
419 EXPECT_CALL(manager_, UpdateEnabledTechnologies()).Times(1);
420 device = NULL;
421}
422
423TEST_F(DeviceInfoTest, CreateDeviceVirtioEthernet) {
424 IPAddress address = CreateInterfaceAddress();
425
426 // VirtioEthernet is identical to Ethernet from the perspective of this test.
427 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
428 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
429 IsIPAddress(address)));
430 DeviceRefPtr device = CreateDevice(
431 kTestDeviceName, "address", kTestDeviceIndex,
432 Technology::kVirtioEthernet);
433 EXPECT_TRUE(device);
434 Mock::VerifyAndClearExpectations(&routing_table_);
435 Mock::VerifyAndClearExpectations(&rtnl_handler_);
436
437 // The Ethernet device destructor notifies the manager.
438 EXPECT_CALL(manager_, UpdateEnabledTechnologies()).Times(1);
439 device = NULL;
440}
441
442TEST_F(DeviceInfoTest, CreateDeviceWiFi) {
443 IPAddress address = CreateInterfaceAddress();
444
445 // WiFi looks a lot like Ethernet too.
446 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
447 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
448 IsIPAddress(address)));
449 EXPECT_TRUE(CreateDevice(
450 kTestDeviceName, "address", kTestDeviceIndex, Technology::kWifi));
451}
452
453TEST_F(DeviceInfoTest, CreateDeviceTunnelAccepted) {
454 IPAddress address = CreateInterfaceAddress();
455
456 // A VPN device should be offered to VPNProvider.
457 StrictMock<MockVPNProvider> vpn_provider;
458 EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&vpn_provider));
459 EXPECT_CALL(vpn_provider,
460 OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
461 .WillOnce(Return(true));
462 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
463 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
464 IsIPAddress(address)));
465 EXPECT_CALL(rtnl_handler_, RemoveInterface(_)).Times(0);
466 EXPECT_FALSE(CreateDevice(
467 kTestDeviceName, "address", kTestDeviceIndex, Technology::kTunnel));
468}
469
470TEST_F(DeviceInfoTest, CreateDeviceTunnelRejected) {
471 IPAddress address = CreateInterfaceAddress();
472
473 // A VPN device should be offered to VPNProvider.
474 StrictMock<MockVPNProvider> vpn_provider;
475 EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&vpn_provider));
476 EXPECT_CALL(vpn_provider,
477 OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
478 .WillOnce(Return(false));
479 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
480 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
481 IsIPAddress(address)));
482 // Since the device was rejected by the VPNProvider, DeviceInfo will
483 // remove the interface.
484 EXPECT_CALL(rtnl_handler_, RemoveInterface(kTestDeviceIndex)).Times(1);
485 EXPECT_FALSE(CreateDevice(
486 kTestDeviceName, "address", kTestDeviceIndex, Technology::kTunnel));
487}
488
489TEST_F(DeviceInfoTest, CreateDevicePPP) {
490 IPAddress address = CreateInterfaceAddress();
491
492 // A VPN device should be offered to VPNProvider.
493 StrictMock<MockVPNProvider> vpn_provider;
494 EXPECT_CALL(manager_, vpn_provider()).WillOnce(Return(&vpn_provider));
495 EXPECT_CALL(vpn_provider,
496 OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
497 .WillOnce(Return(false));
498 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
499 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
500 IsIPAddress(address)));
501 // We do not remove PPP interfaces even if the provider does not accept it.
502 EXPECT_CALL(rtnl_handler_, RemoveInterface(_)).Times(0);
503 EXPECT_FALSE(CreateDevice(
504 kTestDeviceName, "address", kTestDeviceIndex, Technology::kPPP));
505}
506
507TEST_F(DeviceInfoTest, CreateDeviceLoopback) {
508 // A loopback device should be brought up, and nothing else done to it.
509 EXPECT_CALL(routing_table_, FlushRoutes(_)).Times(0);
510 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(_, _)).Times(0);
511 EXPECT_CALL(rtnl_handler_,
512 SetInterfaceFlags(kTestDeviceIndex, IFF_UP, IFF_UP)).Times(1);
513 EXPECT_FALSE(CreateDevice(
514 kTestDeviceName, "address", kTestDeviceIndex, Technology::kLoopback));
515}
516
Paul Stewart050cfc02012-07-06 20:38:54 -0700517TEST_F(DeviceInfoTest, CreateDeviceCDCEthernet) {
518 // A cdc_ether device should be postponed to a task.
519 EXPECT_CALL(manager_, modem_info()).Times(0);
520 EXPECT_CALL(routing_table_, FlushRoutes(_)).Times(0);
521 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(_, _)).Times(0);
522 EXPECT_CALL(dispatcher_,
Paul Stewart1ac4e842012-07-10 12:58:12 -0700523 PostDelayedTask(_, GetDelayedDeviceCreationMilliseconds()));
Paul Stewart050cfc02012-07-06 20:38:54 -0700524 EXPECT_TRUE(GetDelayedDevices().empty());
525 EXPECT_FALSE(CreateDevice(
526 kTestDeviceName, "address", kTestDeviceIndex, Technology::kCDCEthernet));
527 EXPECT_FALSE(GetDelayedDevices().empty());
528 EXPECT_EQ(1, GetDelayedDevices().size());
529 EXPECT_EQ(kTestDeviceIndex, *GetDelayedDevices().begin());
530}
531
Paul Stewart8c116a92012-05-02 18:30:03 -0700532TEST_F(DeviceInfoTest, CreateDeviceUnknown) {
533 IPAddress address = CreateInterfaceAddress();
534
535 // An unknown (blacklisted, unhandled, etc) device won't be flushed or
536 // registered.
537 EXPECT_CALL(routing_table_, FlushRoutes(_)).Times(0);
538 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(_, _)).Times(0);
539 EXPECT_TRUE(CreateDevice(
540 kTestDeviceName, "address", kTestDeviceIndex, Technology::kUnknown));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700541}
542
mukesh agrawal8f317b62011-07-15 11:53:23 -0700543TEST_F(DeviceInfoTest, DeviceBlackList) {
544 device_info_.AddDeviceToBlackList(kTestDeviceName);
Paul Stewart9a908082011-08-31 12:18:48 -0700545 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
Darin Petkove6193c02011-08-11 12:42:40 -0700546 SendMessageToDeviceInfo(*message);
mukesh agrawal8f317b62011-07-15 11:53:23 -0700547
Darin Petkove6193c02011-08-11 12:42:40 -0700548 DeviceRefPtr device = device_info_.GetDevice(kTestDeviceIndex);
549 ASSERT_TRUE(device.get());
Joshua Krollda798622012-06-05 12:30:48 -0700550 EXPECT_TRUE(device->technology() == Technology::kBlacklisted);
mukesh agrawal8f317b62011-07-15 11:53:23 -0700551}
552
Paul Stewart9a908082011-08-31 12:18:48 -0700553TEST_F(DeviceInfoTest, DeviceAddressList) {
Paul Stewart9a908082011-08-31 12:18:48 -0700554 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
555 SendMessageToDeviceInfo(*message);
556
557 vector<DeviceInfo::AddressData> addresses;
558 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
559 EXPECT_TRUE(addresses.empty());
560
561 // Add an address to the device address list
Paul Stewart7355ce12011-09-02 10:47:01 -0700562 IPAddress ip_address0(IPAddress::kFamilyIPv4);
Paul Stewart9a908082011-08-31 12:18:48 -0700563 EXPECT_TRUE(ip_address0.SetAddressFromString(kTestIPAddress0));
564 ip_address0.set_prefix(kTestIPAddressPrefix0);
565 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address0, 0, 0));
566 SendMessageToDeviceInfo(*message);
567 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
568 EXPECT_EQ(1, addresses.size());
569 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
570
571 // Re-adding the same address shouldn't cause the address list to change
572 SendMessageToDeviceInfo(*message);
573 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
574 EXPECT_EQ(1, addresses.size());
575 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
576
577 // Adding a new address should expand the list
Paul Stewart7355ce12011-09-02 10:47:01 -0700578 IPAddress ip_address1(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700579 EXPECT_TRUE(ip_address1.SetAddressFromString(kTestIPAddress1));
580 ip_address1.set_prefix(kTestIPAddressPrefix1);
581 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address1, 0, 0));
582 SendMessageToDeviceInfo(*message);
583 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
584 EXPECT_EQ(2, addresses.size());
585 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
586 EXPECT_TRUE(ip_address1.Equals(addresses[1].address));
587
588 // Deleting an address should reduce the list
589 message.reset(BuildAddressMessage(RTNLMessage::kModeDelete,
590 ip_address0,
591 0,
592 0));
593 SendMessageToDeviceInfo(*message);
594 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
595 EXPECT_EQ(1, addresses.size());
596 EXPECT_TRUE(ip_address1.Equals(addresses[0].address));
597
598 // Delete last item
599 message.reset(BuildAddressMessage(RTNLMessage::kModeDelete,
600 ip_address1,
601 0,
602 0));
603 SendMessageToDeviceInfo(*message);
604 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
605 EXPECT_TRUE(addresses.empty());
606
607 // Delete device
608 message.reset(BuildLinkMessage(RTNLMessage::kModeDelete));
Paul Stewart8c116a92012-05-02 18:30:03 -0700609 EXPECT_CALL(manager_, DeregisterDevice(_)).Times(1);
Paul Stewart9a908082011-08-31 12:18:48 -0700610 SendMessageToDeviceInfo(*message);
611
612 // Should be able to handle message for interface that doesn't exist
613 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address0, 0, 0));
614 SendMessageToDeviceInfo(*message);
615 EXPECT_FALSE(device_info_.GetDevice(kTestDeviceIndex).get());
Paul Stewart9a908082011-08-31 12:18:48 -0700616}
617
618TEST_F(DeviceInfoTest, FlushAddressList) {
Paul Stewart9a908082011-08-31 12:18:48 -0700619 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
620 SendMessageToDeviceInfo(*message);
621
Paul Stewart7355ce12011-09-02 10:47:01 -0700622 IPAddress address1(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700623 EXPECT_TRUE(address1.SetAddressFromString(kTestIPAddress1));
624 address1.set_prefix(kTestIPAddressPrefix1);
625 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
626 address1,
627 0,
628 RT_SCOPE_UNIVERSE));
629 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700630 IPAddress address2(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700631 EXPECT_TRUE(address2.SetAddressFromString(kTestIPAddress2));
632 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
633 address2,
634 IFA_F_TEMPORARY,
635 RT_SCOPE_UNIVERSE));
636 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700637 IPAddress address3(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700638 EXPECT_TRUE(address3.SetAddressFromString(kTestIPAddress3));
639 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
640 address3,
641 0,
642 RT_SCOPE_LINK));
643 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700644 IPAddress address4(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700645 EXPECT_TRUE(address4.SetAddressFromString(kTestIPAddress4));
646 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
647 address4,
648 IFA_F_PERMANENT,
649 RT_SCOPE_UNIVERSE));
650 SendMessageToDeviceInfo(*message);
651
652 // DeviceInfo now has 4 addresses associated with it, but only two of
653 // them are valid for flush.
654 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
655 IsIPAddress(address1)));
656 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
657 IsIPAddress(address2)));
658 device_info_.FlushAddresses(kTestDeviceIndex);
Paul Stewart9a908082011-08-31 12:18:48 -0700659}
660
Paul Stewart05a42c22012-08-02 16:47:21 -0700661TEST_F(DeviceInfoTest, HasOtherAddress) {
662 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
663 SendMessageToDeviceInfo(*message);
664
665 IPAddress address0(IPAddress::kFamilyIPv4);
666 EXPECT_TRUE(address0.SetAddressFromString(kTestIPAddress0));
667
668 // There are no addresses on this interface.
669 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address0));
670
671 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
672 address0,
673 0,
674 RT_SCOPE_UNIVERSE));
675 SendMessageToDeviceInfo(*message);
676
677 IPAddress address1(IPAddress::kFamilyIPv6);
678 EXPECT_TRUE(address1.SetAddressFromString(kTestIPAddress1));
679 address1.set_prefix(kTestIPAddressPrefix1);
680 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
681 address1,
682 0,
683 RT_SCOPE_LINK));
684 SendMessageToDeviceInfo(*message);
685
686 IPAddress address2(IPAddress::kFamilyIPv6);
687 EXPECT_TRUE(address2.SetAddressFromString(kTestIPAddress2));
688 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
689 address2,
690 IFA_F_TEMPORARY,
691 RT_SCOPE_UNIVERSE));
692 SendMessageToDeviceInfo(*message);
693
694 IPAddress address3(IPAddress::kFamilyIPv6);
695 EXPECT_TRUE(address3.SetAddressFromString(kTestIPAddress3));
696
697 // The only IPv6 addresses on this interface are either flagged as
698 // temporary, or they are not universally scoped.
699 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address3));
700
701
702 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
703 address3,
704 0,
705 RT_SCOPE_UNIVERSE));
706 SendMessageToDeviceInfo(*message);
707
708 // address0 is on this interface.
709 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address0));
710 // address1 is on this interface.
711 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address1));
712 // address2 is on this interface.
713 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address2));
714 // address3 is on this interface.
715 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address3));
716
717 IPAddress address4(IPAddress::kFamilyIPv6);
718 EXPECT_TRUE(address4.SetAddressFromString(kTestIPAddress4));
719
720 // address4 is not on this interface, but address3 is, and is a qualified
721 // IPv6 address.
722 EXPECT_TRUE(device_info_.HasOtherAddress(kTestDeviceIndex, address4));
723
724 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
725 address4,
726 IFA_F_PERMANENT,
727 RT_SCOPE_UNIVERSE));
728 SendMessageToDeviceInfo(*message);
729
730 // address4 is now on this interface.
731 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address4));
732
733 IPAddress address5(IPAddress::kFamilyIPv4);
734 EXPECT_TRUE(address5.SetAddressFromString(kTestIPAddress5));
735 // address5 is not on this interface, but address0 is.
736 EXPECT_TRUE(device_info_.HasOtherAddress(kTestDeviceIndex, address5));
737
738 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
739 address5,
740 IFA_F_PERMANENT,
741 RT_SCOPE_UNIVERSE));
742 SendMessageToDeviceInfo(*message);
743
744 // address5 is now on this interface.
745 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address5));
746}
747
Thieu Leb27beee2012-04-20 09:19:06 -0700748TEST_F(DeviceInfoTest, HasSubdir) {
Thieu Le8f1c8352012-04-16 11:02:12 -0700749 ScopedTempDir temp_dir;
750 EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
Thieu Leb27beee2012-04-20 09:19:06 -0700751 EXPECT_TRUE(file_util::CreateDirectory(temp_dir.path().Append("child1")));
752 FilePath child2 = temp_dir.path().Append("child2");
753 EXPECT_TRUE(file_util::CreateDirectory(child2));
754 FilePath grandchild = child2.Append("grandchild");
Thieu Le8f1c8352012-04-16 11:02:12 -0700755 EXPECT_TRUE(file_util::CreateDirectory(grandchild));
756 EXPECT_TRUE(file_util::CreateDirectory(grandchild.Append("greatgrandchild")));
Thieu Leb27beee2012-04-20 09:19:06 -0700757 EXPECT_TRUE(DeviceInfo::HasSubdir(temp_dir.path(),
758 FilePath("grandchild")));
759 EXPECT_TRUE(DeviceInfo::HasSubdir(temp_dir.path(),
760 FilePath("greatgrandchild")));
761 EXPECT_FALSE(DeviceInfo::HasSubdir(temp_dir.path(),
762 FilePath("nonexistent")));
Thieu Le8f1c8352012-04-16 11:02:12 -0700763}
764
Gary Morain41780232012-07-31 15:08:31 -0700765TEST_F(DeviceInfoTest, GetMACAddressFromKernelUnknownDevice) {
766 SetSockets();
767 EXPECT_CALL(*mock_sockets_, Socket(PF_INET, SOCK_DGRAM, 0)).Times(0);
768 ByteString mac_address =
769 device_info_.GetMACAddressFromKernel(kTestDeviceIndex);
770 EXPECT_TRUE(mac_address.IsEmpty());
771}
772
773TEST_F(DeviceInfoTest, GetMACAddressFromKernelUnableToOpenSocket) {
774 SetSockets();
775 EXPECT_CALL(*mock_sockets_, Socket(PF_INET, SOCK_DGRAM, 0))
776 .WillOnce(Return(-1));
777 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
778 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_LOWER_UP, 0));
779 SendMessageToDeviceInfo(*message);
780 EXPECT_TRUE(device_info_.GetDevice(kTestDeviceIndex).get());
781 ByteString mac_address =
782 device_info_.GetMACAddressFromKernel(kTestDeviceIndex);
783 EXPECT_TRUE(mac_address.IsEmpty());
784}
785
786TEST_F(DeviceInfoTest, GetMACAddressFromKernelIoctlFails) {
787 SetSockets();
788 const int kFd = 99;
789 EXPECT_CALL(*mock_sockets_, Socket(PF_INET, SOCK_DGRAM, 0))
790 .WillOnce(Return(kFd));
791 EXPECT_CALL(*mock_sockets_, Ioctl(kFd, SIOCGIFHWADDR, NotNull()))
792 .WillOnce(Return(-1));
793 EXPECT_CALL(*mock_sockets_, Close(kFd));
794
795 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
796 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_LOWER_UP, 0));
797 SendMessageToDeviceInfo(*message);
798 EXPECT_TRUE(device_info_.GetDevice(kTestDeviceIndex).get());
799
800 ByteString mac_address =
801 device_info_.GetMACAddressFromKernel(kTestDeviceIndex);
802 EXPECT_TRUE(mac_address.IsEmpty());
803}
804
805MATCHER_P2(IfreqEquals, ifindex, ifname, "") {
806 const struct ifreq *const ifr = static_cast<struct ifreq *>(arg);
807 return (ifr != NULL) &&
808 (ifr->ifr_ifindex == ifindex) &&
809 (strcmp(ifname, ifr->ifr_name) == 0);
810}
811
812ACTION_P(SetIfreq, ifr) {
813 struct ifreq *const ifr_arg = static_cast<struct ifreq *>(arg2);
814 *ifr_arg = ifr;
815}
816
817TEST_F(DeviceInfoTest, GetMACAddressFromKernel) {
818 SetSockets();
819 const int kFd = 99;
820 struct ifreq ifr;
Han Shenfc349252012-08-30 11:36:04 -0700821 static uint8_t kMacAddress[] = {0x00, 0x01, 0x02, 0xaa, 0xbb, 0xcc};
Gary Morain41780232012-07-31 15:08:31 -0700822 memcpy(ifr.ifr_hwaddr.sa_data, kMacAddress, sizeof(kMacAddress));
823 EXPECT_CALL(*mock_sockets_, Socket(PF_INET, SOCK_DGRAM, 0))
824 .WillOnce(Return(kFd));
825 EXPECT_CALL(*mock_sockets_,
826 Ioctl(kFd, SIOCGIFHWADDR,
827 IfreqEquals(kTestDeviceIndex, kTestDeviceName)))
828 .WillOnce(DoAll(SetIfreq(ifr), Return(0)));
829 EXPECT_CALL(*mock_sockets_, Close(kFd));
830
831 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
832 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_LOWER_UP, 0));
833 SendMessageToDeviceInfo(*message);
834 EXPECT_TRUE(device_info_.GetDevice(kTestDeviceIndex).get());
835
836 ByteString mac_address =
837 device_info_.GetMACAddressFromKernel(kTestDeviceIndex);
838 EXPECT_THAT(kMacAddress,
839 ElementsAreArray(mac_address.GetData(), sizeof(kMacAddress)));
840}
841
Paul Stewartca876ee2012-04-21 08:55:58 -0700842class DeviceInfoTechnologyTest : public DeviceInfoTest {
843 public:
Jason Glasgowabc54032012-04-20 16:08:32 -0400844 DeviceInfoTechnologyTest()
845 : DeviceInfoTest(),
846 test_device_name_(kTestDeviceName) {}
Paul Stewartca876ee2012-04-21 08:55:58 -0700847 virtual ~DeviceInfoTechnologyTest() {}
848
849 virtual void SetUp() {
850 temp_dir_.CreateUniqueTempDir();
851 device_info_root_ = temp_dir_.path().Append("sys/class/net");
852 device_info_.device_info_root_ = device_info_root_;
853 // Most tests require that the uevent file exist.
854 CreateInfoFile("uevent", "xxx");
855 }
856
857 Technology::Identifier GetDeviceTechnology() {
Jason Glasgowabc54032012-04-20 16:08:32 -0400858 return device_info_.GetDeviceTechnology(test_device_name_);
Paul Stewartca876ee2012-04-21 08:55:58 -0700859 }
860 FilePath GetInfoPath(const string &name);
861 void CreateInfoFile(const string &name, const string &contents);
862 void CreateInfoSymLink(const string &name, const string &contents);
Jason Glasgowabc54032012-04-20 16:08:32 -0400863 void SetDeviceName(const string &name) {
864 test_device_name_ = name;
865 SetUp();
866 }
Paul Stewartca876ee2012-04-21 08:55:58 -0700867
868 protected:
869 ScopedTempDir temp_dir_;
870 FilePath device_info_root_;
Jason Glasgowabc54032012-04-20 16:08:32 -0400871 string test_device_name_;
Paul Stewartca876ee2012-04-21 08:55:58 -0700872};
873
874FilePath DeviceInfoTechnologyTest::GetInfoPath(const string &name) {
Jason Glasgowabc54032012-04-20 16:08:32 -0400875 return device_info_root_.Append(test_device_name_).Append(name);
Paul Stewartca876ee2012-04-21 08:55:58 -0700876}
877
878void DeviceInfoTechnologyTest::CreateInfoFile(const string &name,
879 const string &contents) {
880 FilePath info_path = GetInfoPath(name);
881 EXPECT_TRUE(file_util::CreateDirectory(info_path.DirName()));
882 string contents_newline(contents + "\n");
883 EXPECT_TRUE(file_util::WriteFile(info_path, contents_newline.c_str(),
884 contents_newline.size()));
885}
886
887void DeviceInfoTechnologyTest::CreateInfoSymLink(const string &name,
888 const string &contents) {
889 FilePath info_path = GetInfoPath(name);
Paul Stewartca876ee2012-04-21 08:55:58 -0700890 EXPECT_TRUE(file_util::CreateDirectory(info_path.DirName()));
891 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath(contents), info_path));
892}
893
894TEST_F(DeviceInfoTechnologyTest, Unknown) {
895 EXPECT_EQ(Technology::kUnknown, GetDeviceTechnology());
896 // Should still be unknown even without a uevent file.
897 EXPECT_TRUE(file_util::Delete(GetInfoPath("uevent"), FALSE));
898 EXPECT_EQ(Technology::kUnknown, GetDeviceTechnology());
899}
900
901TEST_F(DeviceInfoTechnologyTest, Loopback) {
902 CreateInfoFile("type", base::IntToString(ARPHRD_LOOPBACK));
903 EXPECT_EQ(Technology::kLoopback, GetDeviceTechnology());
904}
905
906TEST_F(DeviceInfoTechnologyTest, PPP) {
907 CreateInfoFile("type", base::IntToString(ARPHRD_PPP));
908 EXPECT_EQ(Technology::kPPP, GetDeviceTechnology());
909}
910
911TEST_F(DeviceInfoTechnologyTest, Tunnel) {
912 CreateInfoFile("tun_flags", base::IntToString(IFF_TUN));
913 EXPECT_EQ(Technology::kTunnel, GetDeviceTechnology());
914}
915
916TEST_F(DeviceInfoTechnologyTest, WiFi) {
917 CreateInfoFile("uevent", "DEVTYPE=wlan");
918 EXPECT_EQ(Technology::kWifi, GetDeviceTechnology());
919 CreateInfoFile("uevent", "foo\nDEVTYPE=wlan");
920 EXPECT_EQ(Technology::kWifi, GetDeviceTechnology());
921 CreateInfoFile("type", base::IntToString(ARPHRD_IEEE80211_RADIOTAP));
922 EXPECT_EQ(Technology::kWiFiMonitor, GetDeviceTechnology());
923}
924
925TEST_F(DeviceInfoTechnologyTest, Ethernet) {
926 CreateInfoSymLink("device/driver", "xxx");
927 EXPECT_EQ(Technology::kEthernet, GetDeviceTechnology());
928}
929
Darin Petkove4b27022012-05-16 13:28:50 +0200930TEST_F(DeviceInfoTechnologyTest, WiMax) {
931 CreateInfoSymLink("device/driver", "gdm_wimax");
932 EXPECT_EQ(Technology::kWiMax, GetDeviceTechnology());
933}
934
Paul Stewartca876ee2012-04-21 08:55:58 -0700935TEST_F(DeviceInfoTechnologyTest, CellularGobi1) {
936 CreateInfoSymLink("device/driver", "blah/foo/gobi");
937 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
938}
939
940TEST_F(DeviceInfoTechnologyTest, CellularGobi2) {
941 CreateInfoSymLink("device/driver", "../GobiNet");
942 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
943}
944
945TEST_F(DeviceInfoTechnologyTest, QCUSB) {
946 CreateInfoSymLink("device/driver", "QCUSBNet2k");
947 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
948}
949
Ben Chan226d46a2012-10-11 00:22:17 -0700950TEST_F(DeviceInfoTechnologyTest, CellularQmiWwan) {
951 CreateInfoSymLink("device/driver", "qmi_wwan");
952 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
953}
954
Paul Stewartca876ee2012-04-21 08:55:58 -0700955// Modem with absolute driver path with top-level tty file:
956// /sys/class/net/dev0/device -> /sys/devices/virtual/0/00
957// /sys/devices/virtual/0/00/driver -> /drivers/cdc_ether
958// /sys/devices/virtual/0/01/tty [empty directory]
959TEST_F(DeviceInfoTechnologyTest, CDCEtherModem1) {
960 FilePath device_root(temp_dir_.path().Append("sys/devices/virtual/0"));
961 FilePath device_path(device_root.Append("00"));
962 EXPECT_TRUE(file_util::CreateDirectory(device_path));
963 CreateInfoSymLink("device", device_path.value());
964 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
965 device_path.Append("driver")));
966 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/tty")));
967 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
968}
969
970// Modem with relative driver path with top-level tty file.
971// /sys/class/net/dev0/device -> ../../../device_dir/0/00
972// /sys/device_dir/0/00/driver -> /drivers/cdc_ether
973// /sys/device_dir/0/01/tty [empty directory]
974TEST_F(DeviceInfoTechnologyTest, CDCEtherModem2) {
975 CreateInfoSymLink("device", "../../../device_dir/0/00");
976 FilePath device_root(temp_dir_.path().Append("sys/device_dir/0"));
977 FilePath device_path(device_root.Append("00"));
978 EXPECT_TRUE(file_util::CreateDirectory(device_path));
979 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
980 device_path.Append("driver")));
981 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/tty")));
982 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
983}
984
985// Modem with relative driver path with lower-level tty file.
986// /sys/class/net/dev0/device -> ../../../device_dir/0/00
987// /sys/device_dir/0/00/driver -> /drivers/cdc_ether
988// /sys/device_dir/0/01/yyy/tty [empty directory]
989TEST_F(DeviceInfoTechnologyTest, CDCEtherModem3) {
990 CreateInfoSymLink("device", "../../../device_dir/0/00");
991 FilePath device_root(temp_dir_.path().Append("sys/device_dir/0"));
992 FilePath device_path(device_root.Append("00"));
993 EXPECT_TRUE(file_util::CreateDirectory(device_path));
994 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
995 device_path.Append("driver")));
996 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/yyy/tty")));
997 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
998}
999
1000TEST_F(DeviceInfoTechnologyTest, CDCEtherNonModem) {
1001 CreateInfoSymLink("device", "device_dir");
1002 CreateInfoSymLink("device_dir/driver", "cdc_ether");
Paul Stewart050cfc02012-07-06 20:38:54 -07001003 EXPECT_EQ(Technology::kCDCEthernet, GetDeviceTechnology());
Paul Stewartca876ee2012-04-21 08:55:58 -07001004}
1005
Jason Glasgowabc54032012-04-20 16:08:32 -04001006TEST_F(DeviceInfoTechnologyTest, PseudoModem) {
1007 SetDeviceName("pseudomodem");
1008 CreateInfoSymLink("device", "device_dir");
1009 CreateInfoSymLink("device_dir/driver", "cdc_ether");
1010 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
1011
1012 SetDeviceName("pseudomodem9");
1013 CreateInfoSymLink("device", "device_dir");
1014 CreateInfoSymLink("device_dir/driver", "cdc_ether");
1015 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
1016}
1017
Paul Stewart050cfc02012-07-06 20:38:54 -07001018class DeviceInfoForDelayedCreationTest : public DeviceInfo {
1019 public:
1020 DeviceInfoForDelayedCreationTest(ControlInterface *control_interface,
1021 EventDispatcher *dispatcher,
1022 Metrics *metrics,
1023 Manager *manager)
1024 : DeviceInfo(control_interface, dispatcher, metrics, manager) {}
1025 MOCK_METHOD4(CreateDevice, DeviceRefPtr(const std::string &link_name,
1026 const std::string &address,
1027 int interface_index,
1028 Technology::Identifier technology));
1029 MOCK_METHOD1(GetDeviceTechnology,
1030 Technology::Identifier(const string &iface_name));
1031};
1032
1033class DeviceInfoDelayedCreationTest : public DeviceInfoTest {
1034 public:
1035 DeviceInfoDelayedCreationTest()
1036 : DeviceInfoTest(),
1037 test_device_info_(
1038 &control_interface_, &dispatcher_, &metrics_, &manager_) {}
1039 virtual ~DeviceInfoDelayedCreationTest() {}
1040
1041 virtual std::set<int> &GetDelayedDevices() {
1042 return test_device_info_.delayed_devices_;
1043 }
1044
1045 void DelayedDeviceCreationTask() {
1046 test_device_info_.DelayedDeviceCreationTask();
1047 }
1048
1049 void AddDelayedDevice() {
1050 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
1051 EXPECT_CALL(test_device_info_, GetDeviceTechnology(kTestDeviceName))
1052 .WillOnce(Return(Technology::kCDCEthernet));
1053 EXPECT_CALL(test_device_info_, CreateDevice(
1054 kTestDeviceName, _, kTestDeviceIndex, Technology::kCDCEthernet))
1055 .WillOnce(Return(DeviceRefPtr()));
1056 test_device_info_.AddLinkMsgHandler(*message);
1057 Mock::VerifyAndClearExpectations(&test_device_info_);
1058 // We need to insert the device index ourselves since we have mocked
1059 // out CreateDevice. This insertion is tested in CreateDeviceCDCEthernet
1060 // above.
1061 GetDelayedDevices().insert(kTestDeviceIndex);
1062 }
1063
1064 protected:
1065 DeviceInfoForDelayedCreationTest test_device_info_;
1066};
1067
1068TEST_F(DeviceInfoDelayedCreationTest, NoDevices) {
1069 EXPECT_TRUE(GetDelayedDevices().empty());
1070 EXPECT_CALL(test_device_info_, GetDeviceTechnology(_)).Times(0);
1071 DelayedDeviceCreationTask();
1072}
1073
1074TEST_F(DeviceInfoDelayedCreationTest, EthernetDevice) {
1075 AddDelayedDevice();
1076 EXPECT_CALL(test_device_info_, GetDeviceTechnology(_))
1077 .WillOnce(Return(Technology::kCDCEthernet));
1078 EXPECT_CALL(test_device_info_, CreateDevice(
1079 kTestDeviceName, _, kTestDeviceIndex, Technology::kEthernet))
1080 .WillOnce(Return(DeviceRefPtr()));
1081 DelayedDeviceCreationTask();
1082 EXPECT_TRUE(GetDelayedDevices().empty());
1083}
1084
1085TEST_F(DeviceInfoDelayedCreationTest, CellularDevice) {
1086 AddDelayedDevice();
1087 EXPECT_CALL(test_device_info_, GetDeviceTechnology(_))
1088 .WillOnce(Return(Technology::kCellular));
1089 EXPECT_CALL(test_device_info_, CreateDevice(
1090 kTestDeviceName, _, kTestDeviceIndex, Technology::kCellular))
1091 .WillOnce(Return(DeviceRefPtr()));
1092 DelayedDeviceCreationTask();
1093 EXPECT_TRUE(GetDelayedDevices().empty());
1094}
1095
Chris Masone9be4a9d2011-05-16 15:44:09 -07001096} // namespace shill