blob: 0d00ecff4fe0bc0d82d58445654b908e6b6cf42d [file] [log] [blame]
Thieu Le3426c8f2012-01-11 17:35:11 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Chris Masone9be4a9d2011-05-16 15:44:09 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Darin Petkov633ac6f2011-07-08 13:56:13 -07004
Chris Masone2aa97072011-08-09 17:35:08 -07005#include "shill/device_info.h"
6
Chris Masone9be4a9d2011-05-16 15:44:09 -07007#include <glib.h>
Darin Petkov633ac6f2011-07-08 13:56:13 -07008#include <sys/socket.h>
Darin Petkove6193c02011-08-11 12:42:40 -07009#include <linux/if.h>
Paul Stewartca876ee2012-04-21 08:55:58 -070010#include <linux/if_tun.h>
Darin Petkov633ac6f2011-07-08 13:56:13 -070011#include <linux/netlink.h> // Needs typedefs from sys/socket.h.
12#include <linux/rtnetlink.h>
Paul Stewartca876ee2012-04-21 08:55:58 -070013#include <net/if_arp.h>
Chris Masone9be4a9d2011-05-16 15:44:09 -070014
Thieu Le8f1c8352012-04-16 11:02:12 -070015#include <base/file_util.h>
Chris Masone9be4a9d2011-05-16 15:44:09 -070016#include <base/logging.h>
17#include <base/memory/ref_counted.h>
18#include <base/message_loop.h>
Thieu Le8f1c8352012-04-16 11:02:12 -070019#include <base/scoped_temp_dir.h>
Eric Shienbrood3e20a232012-02-16 11:35:56 -050020#include <base/stl_util.h>
Paul Stewartca876ee2012-04-21 08:55:58 -070021#include <base/string_number_conversions.h>
Chris Masone9be4a9d2011-05-16 15:44:09 -070022#include <gtest/gtest.h>
23#include <gmock/gmock.h>
24
Paul Stewart9a908082011-08-31 12:18:48 -070025#include "shill/ip_address.h"
Paul Stewartb50f0b92011-05-16 16:31:42 -070026#include "shill/manager.h"
Chris Masone46eaaf52011-05-24 13:08:30 -070027#include "shill/mock_control.h"
Darin Petkovafa6fc42011-06-21 16:21:08 -070028#include "shill/mock_glib.h"
Chris Masone2ae797d2011-08-23 20:41:00 -070029#include "shill/mock_manager.h"
Thieu Le3426c8f2012-01-11 17:35:11 -080030#include "shill/mock_metrics.h"
Paul Stewart9a908082011-08-31 12:18:48 -070031#include "shill/mock_rtnl_handler.h"
Darin Petkov633ac6f2011-07-08 13:56:13 -070032#include "shill/mock_sockets.h"
Chris Masone2aa97072011-08-09 17:35:08 -070033#include "shill/rtnl_message.h"
Chris Masone9be4a9d2011-05-16 15:44:09 -070034
Eric Shienbrood3e20a232012-02-16 11:35:56 -050035using base::Callback;
Darin Petkove6193c02011-08-11 12:42:40 -070036using std::map;
Darin Petkov633ac6f2011-07-08 13:56:13 -070037using std::string;
Paul Stewart9a908082011-08-31 12:18:48 -070038using std::vector;
Darin Petkov633ac6f2011-07-08 13:56:13 -070039using testing::_;
40using testing::Return;
Paul Stewart9a908082011-08-31 12:18:48 -070041using testing::StrictMock;
Darin Petkov633ac6f2011-07-08 13:56:13 -070042using testing::Test;
43
Chris Masone9be4a9d2011-05-16 15:44:09 -070044namespace shill {
Darin Petkov633ac6f2011-07-08 13:56:13 -070045
46class TestEventDispatcher : public EventDispatcher {
47 public:
Paul Stewart26b327e2011-10-19 11:38:09 -070048 virtual IOHandler *CreateInputHandler(
mukesh agrawal1830fa12011-09-26 14:31:40 -070049 int /*fd*/,
Eric Shienbrood3e20a232012-02-16 11:35:56 -050050 const Callback<void(InputData*)> &/*callback*/) {
Darin Petkov633ac6f2011-07-08 13:56:13 -070051 return NULL;
52 }
53};
Chris Masone9be4a9d2011-05-16 15:44:09 -070054
55class DeviceInfoTest : public Test {
56 public:
57 DeviceInfoTest()
Thieu Le3426c8f2012-01-11 17:35:11 -080058 : manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
59 device_info_(&control_interface_, &dispatcher_, &metrics_, &manager_) {
Chris Masone9be4a9d2011-05-16 15:44:09 -070060 }
Paul Stewartca876ee2012-04-21 08:55:58 -070061 virtual ~DeviceInfoTest() {}
Darin Petkov633ac6f2011-07-08 13:56:13 -070062
Paul Stewart9a908082011-08-31 12:18:48 -070063 virtual void SetUp() {
64 device_info_.rtnl_handler_ = &rtnl_handler_;
65 EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestLink |
66 RTNLHandler::kRequestAddr));
67 }
68
Paul Stewarta3c56f92011-05-26 07:08:52 -070069 protected:
Chris Masoneb2e326b2011-07-12 13:28:51 -070070 static const int kTestDeviceIndex;
Darin Petkov633ac6f2011-07-08 13:56:13 -070071 static const char kTestDeviceName[];
Paul Stewart9a908082011-08-31 12:18:48 -070072 static const char kTestMACAddress[];
73 static const char kTestIPAddress0[];
74 static const int kTestIPAddressPrefix0;
75 static const char kTestIPAddress1[];
76 static const int kTestIPAddressPrefix1;
77 static const char kTestIPAddress2[];
78 static const char kTestIPAddress3[];
79 static const char kTestIPAddress4[];
Darin Petkov633ac6f2011-07-08 13:56:13 -070080
Paul Stewart9a908082011-08-31 12:18:48 -070081 RTNLMessage *BuildLinkMessage(RTNLMessage::Mode mode);
Paul Stewarte81eb702012-04-11 15:04:53 -070082 RTNLMessage *BuildLinkMessageWithInterfaceName(RTNLMessage::Mode mode,
83 const string &interface_name);
Paul Stewart9a908082011-08-31 12:18:48 -070084 RTNLMessage *BuildAddressMessage(RTNLMessage::Mode mode,
85 const IPAddress &address,
86 unsigned char flags,
87 unsigned char scope);
Chris Masone2aa97072011-08-09 17:35:08 -070088 void SendMessageToDeviceInfo(const RTNLMessage &message);
Darin Petkov633ac6f2011-07-08 13:56:13 -070089
Darin Petkovafa6fc42011-06-21 16:21:08 -070090 MockGLib glib_;
Chris Masone46eaaf52011-05-24 13:08:30 -070091 MockControl control_interface_;
Thieu Le3426c8f2012-01-11 17:35:11 -080092 MockMetrics metrics_;
Paul Stewart9a908082011-08-31 12:18:48 -070093 StrictMock<MockManager> manager_;
Chris Masone9be4a9d2011-05-16 15:44:09 -070094 DeviceInfo device_info_;
Darin Petkov633ac6f2011-07-08 13:56:13 -070095 TestEventDispatcher dispatcher_;
Paul Stewart9a908082011-08-31 12:18:48 -070096 StrictMock<MockRTNLHandler> rtnl_handler_;
Chris Masone9be4a9d2011-05-16 15:44:09 -070097};
98
Chris Masoneb2e326b2011-07-12 13:28:51 -070099const int DeviceInfoTest::kTestDeviceIndex = 123456;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700100const char DeviceInfoTest::kTestDeviceName[] = "test-device";
Paul Stewart9a908082011-08-31 12:18:48 -0700101const char DeviceInfoTest::kTestMACAddress[] = {
Darin Petkove3e1cfa2011-08-11 13:41:17 -0700102 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
Paul Stewart9a908082011-08-31 12:18:48 -0700103const char DeviceInfoTest::kTestIPAddress0[] = "192.168.1.1";
104const int DeviceInfoTest::kTestIPAddressPrefix0 = 24;
105const char DeviceInfoTest::kTestIPAddress1[] = "fe80::1aa9:5ff:abcd:1234";
106const int DeviceInfoTest::kTestIPAddressPrefix1 = 64;
107const char DeviceInfoTest::kTestIPAddress2[] = "fe80::1aa9:5ff:abcd:1235";
108const char DeviceInfoTest::kTestIPAddress3[] = "fe80::1aa9:5ff:abcd:1236";
109const char DeviceInfoTest::kTestIPAddress4[] = "fe80::1aa9:5ff:abcd:1237";
Chris Masone9be4a9d2011-05-16 15:44:09 -0700110
Paul Stewarte81eb702012-04-11 15:04:53 -0700111RTNLMessage *DeviceInfoTest::BuildLinkMessageWithInterfaceName(
112 RTNLMessage::Mode mode, const string &interface_name) {
Paul Stewart9a908082011-08-31 12:18:48 -0700113 RTNLMessage *message = new RTNLMessage(
114 RTNLMessage::kTypeLink,
115 mode,
116 0,
117 0,
118 0,
119 kTestDeviceIndex,
Paul Stewart7355ce12011-09-02 10:47:01 -0700120 IPAddress::kFamilyIPv4);
Chris Masone2aa97072011-08-09 17:35:08 -0700121 message->SetAttribute(static_cast<uint16>(IFLA_IFNAME),
Paul Stewarte81eb702012-04-11 15:04:53 -0700122 ByteString(interface_name, true));
Paul Stewart9a908082011-08-31 12:18:48 -0700123 ByteString test_address(kTestMACAddress, sizeof(kTestMACAddress));
Chris Masone626719f2011-08-18 16:58:48 -0700124 message->SetAttribute(IFLA_ADDRESS, test_address);
Chris Masone2aa97072011-08-09 17:35:08 -0700125 return message;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700126}
127
Paul Stewarte81eb702012-04-11 15:04:53 -0700128RTNLMessage *DeviceInfoTest::BuildLinkMessage(RTNLMessage::Mode mode) {
129 return BuildLinkMessageWithInterfaceName(mode, kTestDeviceName);
130}
131
Paul Stewart9a908082011-08-31 12:18:48 -0700132RTNLMessage *DeviceInfoTest::BuildAddressMessage(RTNLMessage::Mode mode,
133 const IPAddress &address,
134 unsigned char flags,
135 unsigned char scope) {
136 RTNLMessage *message = new RTNLMessage(
137 RTNLMessage::kTypeAddress,
138 mode,
139 0,
140 0,
141 0,
142 kTestDeviceIndex,
143 address.family());
144 message->SetAttribute(IFA_ADDRESS, address.address());
145 message->set_address_status(
146 RTNLMessage::AddressStatus(address.prefix(), flags, scope));
147 return message;
148}
149
Chris Masone2aa97072011-08-09 17:35:08 -0700150void DeviceInfoTest::SendMessageToDeviceInfo(const RTNLMessage &message) {
Paul Stewart9a908082011-08-31 12:18:48 -0700151 if (message.type() == RTNLMessage::kTypeLink) {
152 device_info_.LinkMsgHandler(message);
153 } else if (message.type() == RTNLMessage::kTypeAddress) {
154 device_info_.AddressMsgHandler(message);
155 } else {
156 NOTREACHED();
157 }
158}
159
160MATCHER_P(IsIPAddress, address, "") {
161 // NB: IPAddress objects don't support the "==" operator as per style, so
162 // we need a custom matcher.
163 return address.Equals(arg);
Darin Petkov633ac6f2011-07-08 13:56:13 -0700164}
165
166TEST_F(DeviceInfoTest, DeviceEnumeration) {
Paul Stewarta3c56f92011-05-26 07:08:52 -0700167 // Start our own private device_info
Chris Masone9be4a9d2011-05-16 15:44:09 -0700168 device_info_.Start();
Paul Stewart9a908082011-08-31 12:18:48 -0700169 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
Darin Petkove6193c02011-08-11 12:42:40 -0700170 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_LOWER_UP, 0));
171 EXPECT_FALSE(device_info_.GetDevice(kTestDeviceIndex).get());
Darin Petkovf8046b82012-04-24 16:29:23 +0200172 EXPECT_EQ(-1, device_info_.GetIndex(kTestDeviceName));
Darin Petkove6193c02011-08-11 12:42:40 -0700173 SendMessageToDeviceInfo(*message);
174 EXPECT_TRUE(device_info_.GetDevice(kTestDeviceIndex).get());
175 unsigned int flags = 0;
176 EXPECT_TRUE(device_info_.GetFlags(kTestDeviceIndex, &flags));
177 EXPECT_EQ(IFF_LOWER_UP, flags);
Darin Petkove3e1cfa2011-08-11 13:41:17 -0700178 ByteString address;
Paul Stewart32852962011-08-30 14:06:53 -0700179 EXPECT_TRUE(device_info_.GetMACAddress(kTestDeviceIndex, &address));
Darin Petkove3e1cfa2011-08-11 13:41:17 -0700180 EXPECT_FALSE(address.IsEmpty());
Paul Stewart9a908082011-08-31 12:18:48 -0700181 EXPECT_TRUE(address.Equals(ByteString(kTestMACAddress,
182 sizeof(kTestMACAddress))));
Darin Petkovf8046b82012-04-24 16:29:23 +0200183 EXPECT_EQ(kTestDeviceIndex, device_info_.GetIndex(kTestDeviceName));
Paul Stewarta3c56f92011-05-26 07:08:52 -0700184
Paul Stewart9a908082011-08-31 12:18:48 -0700185 message.reset(BuildLinkMessage(RTNLMessage::kModeAdd));
Darin Petkove6193c02011-08-11 12:42:40 -0700186 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_UP | IFF_RUNNING, 0));
187 SendMessageToDeviceInfo(*message);
188 EXPECT_TRUE(device_info_.GetFlags(kTestDeviceIndex, &flags));
189 EXPECT_EQ(IFF_UP | IFF_RUNNING, flags);
Paul Stewartb50f0b92011-05-16 16:31:42 -0700190
Paul Stewart9a908082011-08-31 12:18:48 -0700191 message.reset(BuildLinkMessage(RTNLMessage::kModeDelete));
Darin Petkove6193c02011-08-11 12:42:40 -0700192 SendMessageToDeviceInfo(*message);
193 EXPECT_FALSE(device_info_.GetDevice(kTestDeviceIndex).get());
194 EXPECT_FALSE(device_info_.GetFlags(kTestDeviceIndex, NULL));
Darin Petkovf8046b82012-04-24 16:29:23 +0200195 EXPECT_EQ(-1, device_info_.GetIndex(kTestDeviceName));
Paul Stewarta3c56f92011-05-26 07:08:52 -0700196
Paul Stewarta3c56f92011-05-26 07:08:52 -0700197 device_info_.Stop();
Chris Masone9be4a9d2011-05-16 15:44:09 -0700198}
199
mukesh agrawal8f317b62011-07-15 11:53:23 -0700200TEST_F(DeviceInfoTest, DeviceBlackList) {
201 device_info_.AddDeviceToBlackList(kTestDeviceName);
202 device_info_.Start();
Paul Stewart9a908082011-08-31 12:18:48 -0700203 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
Darin Petkove6193c02011-08-11 12:42:40 -0700204 SendMessageToDeviceInfo(*message);
mukesh agrawal8f317b62011-07-15 11:53:23 -0700205
Darin Petkove6193c02011-08-11 12:42:40 -0700206 DeviceRefPtr device = device_info_.GetDevice(kTestDeviceIndex);
207 ASSERT_TRUE(device.get());
Paul Stewartfdd16072011-09-16 12:41:35 -0700208 EXPECT_TRUE(device->TechnologyIs(Technology::kBlacklisted));
mukesh agrawal8f317b62011-07-15 11:53:23 -0700209
mukesh agrawal8f317b62011-07-15 11:53:23 -0700210 device_info_.Stop();
211}
212
Paul Stewart9a908082011-08-31 12:18:48 -0700213TEST_F(DeviceInfoTest, DeviceAddressList) {
214 device_info_.Start();
215 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
216 SendMessageToDeviceInfo(*message);
217
218 vector<DeviceInfo::AddressData> addresses;
219 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
220 EXPECT_TRUE(addresses.empty());
221
222 // Add an address to the device address list
Paul Stewart7355ce12011-09-02 10:47:01 -0700223 IPAddress ip_address0(IPAddress::kFamilyIPv4);
Paul Stewart9a908082011-08-31 12:18:48 -0700224 EXPECT_TRUE(ip_address0.SetAddressFromString(kTestIPAddress0));
225 ip_address0.set_prefix(kTestIPAddressPrefix0);
226 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address0, 0, 0));
227 SendMessageToDeviceInfo(*message);
228 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
229 EXPECT_EQ(1, addresses.size());
230 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
231
232 // Re-adding the same address shouldn't cause the address list to change
233 SendMessageToDeviceInfo(*message);
234 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
235 EXPECT_EQ(1, addresses.size());
236 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
237
238 // Adding a new address should expand the list
Paul Stewart7355ce12011-09-02 10:47:01 -0700239 IPAddress ip_address1(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700240 EXPECT_TRUE(ip_address1.SetAddressFromString(kTestIPAddress1));
241 ip_address1.set_prefix(kTestIPAddressPrefix1);
242 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address1, 0, 0));
243 SendMessageToDeviceInfo(*message);
244 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
245 EXPECT_EQ(2, addresses.size());
246 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
247 EXPECT_TRUE(ip_address1.Equals(addresses[1].address));
248
249 // Deleting an address should reduce the list
250 message.reset(BuildAddressMessage(RTNLMessage::kModeDelete,
251 ip_address0,
252 0,
253 0));
254 SendMessageToDeviceInfo(*message);
255 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
256 EXPECT_EQ(1, addresses.size());
257 EXPECT_TRUE(ip_address1.Equals(addresses[0].address));
258
259 // Delete last item
260 message.reset(BuildAddressMessage(RTNLMessage::kModeDelete,
261 ip_address1,
262 0,
263 0));
264 SendMessageToDeviceInfo(*message);
265 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
266 EXPECT_TRUE(addresses.empty());
267
268 // Delete device
269 message.reset(BuildLinkMessage(RTNLMessage::kModeDelete));
270 SendMessageToDeviceInfo(*message);
271
272 // Should be able to handle message for interface that doesn't exist
273 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address0, 0, 0));
274 SendMessageToDeviceInfo(*message);
275 EXPECT_FALSE(device_info_.GetDevice(kTestDeviceIndex).get());
276
277 device_info_.Stop();
278}
279
280TEST_F(DeviceInfoTest, FlushAddressList) {
281 device_info_.Start();
282 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
283 SendMessageToDeviceInfo(*message);
284
Paul Stewart7355ce12011-09-02 10:47:01 -0700285 IPAddress address1(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700286 EXPECT_TRUE(address1.SetAddressFromString(kTestIPAddress1));
287 address1.set_prefix(kTestIPAddressPrefix1);
288 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
289 address1,
290 0,
291 RT_SCOPE_UNIVERSE));
292 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700293 IPAddress address2(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700294 EXPECT_TRUE(address2.SetAddressFromString(kTestIPAddress2));
295 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
296 address2,
297 IFA_F_TEMPORARY,
298 RT_SCOPE_UNIVERSE));
299 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700300 IPAddress address3(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700301 EXPECT_TRUE(address3.SetAddressFromString(kTestIPAddress3));
302 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
303 address3,
304 0,
305 RT_SCOPE_LINK));
306 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700307 IPAddress address4(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700308 EXPECT_TRUE(address4.SetAddressFromString(kTestIPAddress4));
309 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
310 address4,
311 IFA_F_PERMANENT,
312 RT_SCOPE_UNIVERSE));
313 SendMessageToDeviceInfo(*message);
314
315 // DeviceInfo now has 4 addresses associated with it, but only two of
316 // them are valid for flush.
317 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
318 IsIPAddress(address1)));
319 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
320 IsIPAddress(address2)));
321 device_info_.FlushAddresses(kTestDeviceIndex);
322 device_info_.Stop();
323}
324
Thieu Leb27beee2012-04-20 09:19:06 -0700325TEST_F(DeviceInfoTest, HasSubdir) {
Thieu Le8f1c8352012-04-16 11:02:12 -0700326 device_info_.Start();
327 ScopedTempDir temp_dir;
328 EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
Thieu Leb27beee2012-04-20 09:19:06 -0700329 EXPECT_TRUE(file_util::CreateDirectory(temp_dir.path().Append("child1")));
330 FilePath child2 = temp_dir.path().Append("child2");
331 EXPECT_TRUE(file_util::CreateDirectory(child2));
332 FilePath grandchild = child2.Append("grandchild");
Thieu Le8f1c8352012-04-16 11:02:12 -0700333 EXPECT_TRUE(file_util::CreateDirectory(grandchild));
334 EXPECT_TRUE(file_util::CreateDirectory(grandchild.Append("greatgrandchild")));
Thieu Leb27beee2012-04-20 09:19:06 -0700335 EXPECT_TRUE(DeviceInfo::HasSubdir(temp_dir.path(),
336 FilePath("grandchild")));
337 EXPECT_TRUE(DeviceInfo::HasSubdir(temp_dir.path(),
338 FilePath("greatgrandchild")));
339 EXPECT_FALSE(DeviceInfo::HasSubdir(temp_dir.path(),
340 FilePath("nonexistent")));
Thieu Le8f1c8352012-04-16 11:02:12 -0700341}
342
Paul Stewartca876ee2012-04-21 08:55:58 -0700343class DeviceInfoTechnologyTest : public DeviceInfoTest {
344 public:
345 DeviceInfoTechnologyTest() : DeviceInfoTest() {}
346 virtual ~DeviceInfoTechnologyTest() {}
347
348 virtual void SetUp() {
349 temp_dir_.CreateUniqueTempDir();
350 device_info_root_ = temp_dir_.path().Append("sys/class/net");
351 device_info_.device_info_root_ = device_info_root_;
352 // Most tests require that the uevent file exist.
353 CreateInfoFile("uevent", "xxx");
354 }
355
356 Technology::Identifier GetDeviceTechnology() {
357 return device_info_.GetDeviceTechnology(kTestDeviceName);
358 }
359 FilePath GetInfoPath(const string &name);
360 void CreateInfoFile(const string &name, const string &contents);
361 void CreateInfoSymLink(const string &name, const string &contents);
362
363 protected:
364 ScopedTempDir temp_dir_;
365 FilePath device_info_root_;
366};
367
368FilePath DeviceInfoTechnologyTest::GetInfoPath(const string &name) {
369 return device_info_root_.Append(kTestDeviceName).Append(name);
370}
371
372void DeviceInfoTechnologyTest::CreateInfoFile(const string &name,
373 const string &contents) {
374 FilePath info_path = GetInfoPath(name);
375 EXPECT_TRUE(file_util::CreateDirectory(info_path.DirName()));
376 string contents_newline(contents + "\n");
377 EXPECT_TRUE(file_util::WriteFile(info_path, contents_newline.c_str(),
378 contents_newline.size()));
379}
380
381void DeviceInfoTechnologyTest::CreateInfoSymLink(const string &name,
382 const string &contents) {
383 FilePath info_path = GetInfoPath(name);
Paul Stewartca876ee2012-04-21 08:55:58 -0700384 EXPECT_TRUE(file_util::CreateDirectory(info_path.DirName()));
385 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath(contents), info_path));
386}
387
388TEST_F(DeviceInfoTechnologyTest, Unknown) {
389 EXPECT_EQ(Technology::kUnknown, GetDeviceTechnology());
390 // Should still be unknown even without a uevent file.
391 EXPECT_TRUE(file_util::Delete(GetInfoPath("uevent"), FALSE));
392 EXPECT_EQ(Technology::kUnknown, GetDeviceTechnology());
393}
394
395TEST_F(DeviceInfoTechnologyTest, Loopback) {
396 CreateInfoFile("type", base::IntToString(ARPHRD_LOOPBACK));
397 EXPECT_EQ(Technology::kLoopback, GetDeviceTechnology());
398}
399
400TEST_F(DeviceInfoTechnologyTest, PPP) {
401 CreateInfoFile("type", base::IntToString(ARPHRD_PPP));
402 EXPECT_EQ(Technology::kPPP, GetDeviceTechnology());
403}
404
405TEST_F(DeviceInfoTechnologyTest, Tunnel) {
406 CreateInfoFile("tun_flags", base::IntToString(IFF_TUN));
407 EXPECT_EQ(Technology::kTunnel, GetDeviceTechnology());
408}
409
410TEST_F(DeviceInfoTechnologyTest, WiFi) {
411 CreateInfoFile("uevent", "DEVTYPE=wlan");
412 EXPECT_EQ(Technology::kWifi, GetDeviceTechnology());
413 CreateInfoFile("uevent", "foo\nDEVTYPE=wlan");
414 EXPECT_EQ(Technology::kWifi, GetDeviceTechnology());
415 CreateInfoFile("type", base::IntToString(ARPHRD_IEEE80211_RADIOTAP));
416 EXPECT_EQ(Technology::kWiFiMonitor, GetDeviceTechnology());
417}
418
419TEST_F(DeviceInfoTechnologyTest, Ethernet) {
420 CreateInfoSymLink("device/driver", "xxx");
421 EXPECT_EQ(Technology::kEthernet, GetDeviceTechnology());
422}
423
424TEST_F(DeviceInfoTechnologyTest, CellularGobi1) {
425 CreateInfoSymLink("device/driver", "blah/foo/gobi");
426 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
427}
428
429TEST_F(DeviceInfoTechnologyTest, CellularGobi2) {
430 CreateInfoSymLink("device/driver", "../GobiNet");
431 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
432}
433
434TEST_F(DeviceInfoTechnologyTest, QCUSB) {
435 CreateInfoSymLink("device/driver", "QCUSBNet2k");
436 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
437}
438
439// Modem with absolute driver path with top-level tty file:
440// /sys/class/net/dev0/device -> /sys/devices/virtual/0/00
441// /sys/devices/virtual/0/00/driver -> /drivers/cdc_ether
442// /sys/devices/virtual/0/01/tty [empty directory]
443TEST_F(DeviceInfoTechnologyTest, CDCEtherModem1) {
444 FilePath device_root(temp_dir_.path().Append("sys/devices/virtual/0"));
445 FilePath device_path(device_root.Append("00"));
446 EXPECT_TRUE(file_util::CreateDirectory(device_path));
447 CreateInfoSymLink("device", device_path.value());
448 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
449 device_path.Append("driver")));
450 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/tty")));
451 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
452}
453
454// Modem with relative driver path with top-level tty file.
455// /sys/class/net/dev0/device -> ../../../device_dir/0/00
456// /sys/device_dir/0/00/driver -> /drivers/cdc_ether
457// /sys/device_dir/0/01/tty [empty directory]
458TEST_F(DeviceInfoTechnologyTest, CDCEtherModem2) {
459 CreateInfoSymLink("device", "../../../device_dir/0/00");
460 FilePath device_root(temp_dir_.path().Append("sys/device_dir/0"));
461 FilePath device_path(device_root.Append("00"));
462 EXPECT_TRUE(file_util::CreateDirectory(device_path));
463 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
464 device_path.Append("driver")));
465 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/tty")));
466 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
467}
468
469// Modem with relative driver path with lower-level tty file.
470// /sys/class/net/dev0/device -> ../../../device_dir/0/00
471// /sys/device_dir/0/00/driver -> /drivers/cdc_ether
472// /sys/device_dir/0/01/yyy/tty [empty directory]
473TEST_F(DeviceInfoTechnologyTest, CDCEtherModem3) {
474 CreateInfoSymLink("device", "../../../device_dir/0/00");
475 FilePath device_root(temp_dir_.path().Append("sys/device_dir/0"));
476 FilePath device_path(device_root.Append("00"));
477 EXPECT_TRUE(file_util::CreateDirectory(device_path));
478 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
479 device_path.Append("driver")));
480 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/yyy/tty")));
481 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
482}
483
484TEST_F(DeviceInfoTechnologyTest, CDCEtherNonModem) {
485 CreateInfoSymLink("device", "device_dir");
486 CreateInfoSymLink("device_dir/driver", "cdc_ether");
487 EXPECT_EQ(Technology::kEthernet, GetDeviceTechnology());
488}
489
Chris Masone9be4a9d2011-05-16 15:44:09 -0700490} // namespace shill