blob: 2d1a8c8a8d7ea2e03d41b23528dffb5571471215 [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 Petkove6193c02011-08-11 12:42:40 -07008#include <linux/if.h>
Paul Stewartca876ee2012-04-21 08:55:58 -07009#include <linux/if_tun.h>
Darin Petkov633ac6f2011-07-08 13:56:13 -070010#include <linux/netlink.h> // Needs typedefs from sys/socket.h.
11#include <linux/rtnetlink.h>
Gary Morain41780232012-07-31 15:08:31 -070012#include <linux/sockios.h>
Paul Stewartca876ee2012-04-21 08:55:58 -070013#include <net/if_arp.h>
Wade Guthrie7347bf22013-04-30 11:21:51 -070014#include <sys/socket.h>
Chris Masone9be4a9d2011-05-16 15:44:09 -070015
Paul Stewart2ddf2c62013-04-16 09:47:34 -070016#include <base/bind.h>
Thieu Le8f1c8352012-04-16 11:02:12 -070017#include <base/file_util.h>
Paul Stewart5ad16062013-02-21 18:10:48 -080018#include <base/files/scoped_temp_dir.h>
Chris Masone9be4a9d2011-05-16 15:44:09 -070019#include <base/memory/ref_counted.h>
20#include <base/message_loop.h>
Eric Shienbrood3e20a232012-02-16 11:35:56 -050021#include <base/stl_util.h>
Paul Stewartca876ee2012-04-21 08:55:58 -070022#include <base/string_number_conversions.h>
Chris Masone9be4a9d2011-05-16 15:44:09 -070023#include <gmock/gmock.h>
Ben Chan5086b972013-01-15 21:51:38 -080024#include <gtest/gtest.h>
Chris Masone9be4a9d2011-05-16 15:44:09 -070025
Paul Stewart9a908082011-08-31 12:18:48 -070026#include "shill/ip_address.h"
Christopher Wileyb691efd2012-08-09 13:51:51 -070027#include "shill/logging.h"
Paul Stewartb50f0b92011-05-16 16:31:42 -070028#include "shill/manager.h"
Chris Masone46eaaf52011-05-24 13:08:30 -070029#include "shill/mock_control.h"
Ben Chan5086b972013-01-15 21:51:38 -080030#include "shill/mock_device.h"
Darin Petkovafa6fc42011-06-21 16:21:08 -070031#include "shill/mock_glib.h"
Paul Stewart2ddf2c62013-04-16 09:47:34 -070032#include "shill/mock_log.h"
Chris Masone2ae797d2011-08-23 20:41:00 -070033#include "shill/mock_manager.h"
Thieu Le3426c8f2012-01-11 17:35:11 -080034#include "shill/mock_metrics.h"
Paul Stewart8c116a92012-05-02 18:30:03 -070035#include "shill/mock_modem_info.h"
Paul Stewart2ddf2c62013-04-16 09:47:34 -070036#include "shill/mock_netlink_manager.h"
Paul Stewart8c116a92012-05-02 18:30:03 -070037#include "shill/mock_routing_table.h"
Paul Stewart9a908082011-08-31 12:18:48 -070038#include "shill/mock_rtnl_handler.h"
Darin Petkov633ac6f2011-07-08 13:56:13 -070039#include "shill/mock_sockets.h"
Paul Stewart8c116a92012-05-02 18:30:03 -070040#include "shill/mock_vpn_provider.h"
Darin Petkove4b27022012-05-16 13:28:50 +020041#include "shill/mock_wimax_provider.h"
Paul Stewart2ddf2c62013-04-16 09:47:34 -070042#include "shill/netlink_attribute.h"
43#include "shill/nl80211_message.h"
Chris Masone2aa97072011-08-09 17:35:08 -070044#include "shill/rtnl_message.h"
Darin Petkovc63dcf02012-05-24 11:51:43 +020045#include "shill/wimax.h"
Chris Masone9be4a9d2011-05-16 15:44:09 -070046
Eric Shienbrood3e20a232012-02-16 11:35:56 -050047using base::Callback;
Albert Chaulk0e1cdea2013-02-27 15:32:55 -080048using base::FilePath;
Darin Petkove6193c02011-08-11 12:42:40 -070049using std::map;
Ben Chan5086b972013-01-15 21:51:38 -080050using std::set;
Darin Petkov633ac6f2011-07-08 13:56:13 -070051using std::string;
Paul Stewart9a908082011-08-31 12:18:48 -070052using std::vector;
Darin Petkov633ac6f2011-07-08 13:56:13 -070053using testing::_;
Paul Stewart2ddf2c62013-04-16 09:47:34 -070054using testing::AnyNumber;
Ben Chan5086b972013-01-15 21:51:38 -080055using testing::ContainerEq;
Gary Morain41780232012-07-31 15:08:31 -070056using testing::DoAll;
57using testing::ElementsAreArray;
Paul Stewart2ddf2c62013-04-16 09:47:34 -070058using testing::HasSubstr;
Paul Stewart8c116a92012-05-02 18:30:03 -070059using testing::Mock;
Gary Morain41780232012-07-31 15:08:31 -070060using testing::NotNull;
Darin Petkov633ac6f2011-07-08 13:56:13 -070061using testing::Return;
Paul Stewart9a908082011-08-31 12:18:48 -070062using testing::StrictMock;
Darin Petkov633ac6f2011-07-08 13:56:13 -070063using testing::Test;
64
Chris Masone9be4a9d2011-05-16 15:44:09 -070065namespace shill {
Darin Petkov633ac6f2011-07-08 13:56:13 -070066
Paul Stewart050cfc02012-07-06 20:38:54 -070067class TestEventDispatcherForDeviceInfo : public EventDispatcher {
Darin Petkov633ac6f2011-07-08 13:56:13 -070068 public:
Paul Stewart26b327e2011-10-19 11:38:09 -070069 virtual IOHandler *CreateInputHandler(
mukesh agrawal1830fa12011-09-26 14:31:40 -070070 int /*fd*/,
Paul Stewart5f06a0e2012-12-20 11:11:33 -080071 const IOHandler::InputCallback &/*input_callback*/,
72 const IOHandler::ErrorCallback &/*error_callback*/) {
Darin Petkov633ac6f2011-07-08 13:56:13 -070073 return NULL;
74 }
Paul Stewart050cfc02012-07-06 20:38:54 -070075 MOCK_METHOD2(PostDelayedTask, bool(const base::Closure &task,
76 int64 delay_ms));
Darin Petkov633ac6f2011-07-08 13:56:13 -070077};
Chris Masone9be4a9d2011-05-16 15:44:09 -070078
79class DeviceInfoTest : public Test {
80 public:
81 DeviceInfoTest()
Thieu Le6c1e3bb2013-02-06 15:20:35 -080082 : metrics_(&dispatcher_),
83 manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
Thieu Le3426c8f2012-01-11 17:35:11 -080084 device_info_(&control_interface_, &dispatcher_, &metrics_, &manager_) {
Chris Masone9be4a9d2011-05-16 15:44:09 -070085 }
Paul Stewartca876ee2012-04-21 08:55:58 -070086 virtual ~DeviceInfoTest() {}
Darin Petkov633ac6f2011-07-08 13:56:13 -070087
Paul Stewart9a908082011-08-31 12:18:48 -070088 virtual void SetUp() {
89 device_info_.rtnl_handler_ = &rtnl_handler_;
Paul Stewart8c116a92012-05-02 18:30:03 -070090 device_info_.routing_table_ = &routing_table_;
Paul Stewart2ddf2c62013-04-16 09:47:34 -070091 device_info_.netlink_manager_ = &netlink_manager_;
Paul Stewart9a908082011-08-31 12:18:48 -070092 }
93
Paul Stewart8c116a92012-05-02 18:30:03 -070094 IPAddress CreateInterfaceAddress() {
95 // Create an IP address entry (as if left-over from a previous connection
96 // manager).
97 IPAddress address(IPAddress::kFamilyIPv4);
98 EXPECT_TRUE(address.SetAddressFromString(kTestIPAddress0));
99 address.set_prefix(kTestIPAddressPrefix0);
100 vector<DeviceInfo::AddressData> &addresses =
101 device_info_.infos_[kTestDeviceIndex].ip_addresses;
102 addresses.push_back(DeviceInfo::AddressData(address, 0, RT_SCOPE_UNIVERSE));
103 EXPECT_EQ(1, addresses.size());
104 return address;
105 }
106
107 DeviceRefPtr CreateDevice(const std::string &link_name,
108 const std::string &address,
109 int interface_index,
110 Technology::Identifier technology) {
111 return device_info_.CreateDevice(link_name, address, interface_index,
112 technology);
113 }
114
Paul Stewart050cfc02012-07-06 20:38:54 -0700115 virtual std::set<int> &GetDelayedDevices() {
116 return device_info_.delayed_devices_;
117 }
118
Paul Stewart1ac4e842012-07-10 12:58:12 -0700119 int GetDelayedDeviceCreationMilliseconds() {
Paul Stewart050cfc02012-07-06 20:38:54 -0700120 return DeviceInfo::kDelayedDeviceCreationSeconds * 1000;
121 }
Paul Stewart8c116a92012-05-02 18:30:03 -0700122
Gary Morain41780232012-07-31 15:08:31 -0700123 void SetSockets() {
124 mock_sockets_ = new MockSockets();
125 device_info_.set_sockets(mock_sockets_);
126 }
127
Darin Petkovc3505a52013-03-18 15:13:29 +0100128 // Takes ownership of |provider|.
129 void SetVPNProvider(VPNProvider *provider) {
130 manager_.vpn_provider_.reset(provider);
Paul Stewartb87d22b2013-07-29 11:11:37 -0700131 manager_.UpdateProviderMapping();
Darin Petkovc3505a52013-03-18 15:13:29 +0100132 }
133
Paul Stewarta3c56f92011-05-26 07:08:52 -0700134 protected:
Chris Masoneb2e326b2011-07-12 13:28:51 -0700135 static const int kTestDeviceIndex;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700136 static const char kTestDeviceName[];
Han Shenfc349252012-08-30 11:36:04 -0700137 static const uint8_t kTestMACAddress[];
Paul Stewart9a908082011-08-31 12:18:48 -0700138 static const char kTestIPAddress0[];
139 static const int kTestIPAddressPrefix0;
140 static const char kTestIPAddress1[];
141 static const int kTestIPAddressPrefix1;
142 static const char kTestIPAddress2[];
143 static const char kTestIPAddress3[];
144 static const char kTestIPAddress4[];
Paul Stewart05a42c22012-08-02 16:47:21 -0700145 static const char kTestIPAddress5[];
Paul Stewart1ac4e842012-07-10 12:58:12 -0700146 static const int kReceiveByteCount;
147 static const int kTransmitByteCount;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700148
Paul Stewart9a908082011-08-31 12:18:48 -0700149 RTNLMessage *BuildLinkMessage(RTNLMessage::Mode mode);
Paul Stewarte81eb702012-04-11 15:04:53 -0700150 RTNLMessage *BuildLinkMessageWithInterfaceName(RTNLMessage::Mode mode,
151 const string &interface_name);
Paul Stewart9a908082011-08-31 12:18:48 -0700152 RTNLMessage *BuildAddressMessage(RTNLMessage::Mode mode,
153 const IPAddress &address,
154 unsigned char flags,
155 unsigned char scope);
Chris Masone2aa97072011-08-09 17:35:08 -0700156 void SendMessageToDeviceInfo(const RTNLMessage &message);
Darin Petkov633ac6f2011-07-08 13:56:13 -0700157
Darin Petkovafa6fc42011-06-21 16:21:08 -0700158 MockGLib glib_;
Chris Masone46eaaf52011-05-24 13:08:30 -0700159 MockControl control_interface_;
Thieu Le3426c8f2012-01-11 17:35:11 -0800160 MockMetrics metrics_;
Paul Stewart9a908082011-08-31 12:18:48 -0700161 StrictMock<MockManager> manager_;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700162 DeviceInfo device_info_;
Paul Stewart050cfc02012-07-06 20:38:54 -0700163 TestEventDispatcherForDeviceInfo dispatcher_;
Paul Stewart8c116a92012-05-02 18:30:03 -0700164 MockRoutingTable routing_table_;
Paul Stewart2ddf2c62013-04-16 09:47:34 -0700165 MockNetlinkManager netlink_manager_;
Paul Stewart9a908082011-08-31 12:18:48 -0700166 StrictMock<MockRTNLHandler> rtnl_handler_;
Gary Morain41780232012-07-31 15:08:31 -0700167 MockSockets *mock_sockets_; // Owned by DeviceInfo.
Chris Masone9be4a9d2011-05-16 15:44:09 -0700168};
169
Chris Masoneb2e326b2011-07-12 13:28:51 -0700170const int DeviceInfoTest::kTestDeviceIndex = 123456;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700171const char DeviceInfoTest::kTestDeviceName[] = "test-device";
Han Shenfc349252012-08-30 11:36:04 -0700172const uint8_t DeviceInfoTest::kTestMACAddress[] = {
Wade Guthrie7347bf22013-04-30 11:21:51 -0700173 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
Paul Stewart9a908082011-08-31 12:18:48 -0700174const char DeviceInfoTest::kTestIPAddress0[] = "192.168.1.1";
175const int DeviceInfoTest::kTestIPAddressPrefix0 = 24;
176const char DeviceInfoTest::kTestIPAddress1[] = "fe80::1aa9:5ff:abcd:1234";
177const int DeviceInfoTest::kTestIPAddressPrefix1 = 64;
178const char DeviceInfoTest::kTestIPAddress2[] = "fe80::1aa9:5ff:abcd:1235";
179const char DeviceInfoTest::kTestIPAddress3[] = "fe80::1aa9:5ff:abcd:1236";
180const char DeviceInfoTest::kTestIPAddress4[] = "fe80::1aa9:5ff:abcd:1237";
Paul Stewart05a42c22012-08-02 16:47:21 -0700181const char DeviceInfoTest::kTestIPAddress5[] = "192.168.1.2";
Paul Stewart1ac4e842012-07-10 12:58:12 -0700182const int DeviceInfoTest::kReceiveByteCount = 1234;
183const int DeviceInfoTest::kTransmitByteCount = 5678;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700184
Paul Stewarte81eb702012-04-11 15:04:53 -0700185RTNLMessage *DeviceInfoTest::BuildLinkMessageWithInterfaceName(
186 RTNLMessage::Mode mode, const string &interface_name) {
Paul Stewart9a908082011-08-31 12:18:48 -0700187 RTNLMessage *message = new RTNLMessage(
188 RTNLMessage::kTypeLink,
189 mode,
190 0,
191 0,
192 0,
193 kTestDeviceIndex,
Paul Stewart7355ce12011-09-02 10:47:01 -0700194 IPAddress::kFamilyIPv4);
Chris Masone2aa97072011-08-09 17:35:08 -0700195 message->SetAttribute(static_cast<uint16>(IFLA_IFNAME),
Paul Stewarte81eb702012-04-11 15:04:53 -0700196 ByteString(interface_name, true));
Paul Stewart9a908082011-08-31 12:18:48 -0700197 ByteString test_address(kTestMACAddress, sizeof(kTestMACAddress));
Chris Masone626719f2011-08-18 16:58:48 -0700198 message->SetAttribute(IFLA_ADDRESS, test_address);
Chris Masone2aa97072011-08-09 17:35:08 -0700199 return message;
Darin Petkov633ac6f2011-07-08 13:56:13 -0700200}
201
Paul Stewarte81eb702012-04-11 15:04:53 -0700202RTNLMessage *DeviceInfoTest::BuildLinkMessage(RTNLMessage::Mode mode) {
203 return BuildLinkMessageWithInterfaceName(mode, kTestDeviceName);
204}
205
Paul Stewart9a908082011-08-31 12:18:48 -0700206RTNLMessage *DeviceInfoTest::BuildAddressMessage(RTNLMessage::Mode mode,
207 const IPAddress &address,
208 unsigned char flags,
209 unsigned char scope) {
210 RTNLMessage *message = new RTNLMessage(
211 RTNLMessage::kTypeAddress,
212 mode,
213 0,
214 0,
215 0,
216 kTestDeviceIndex,
217 address.family());
218 message->SetAttribute(IFA_ADDRESS, address.address());
219 message->set_address_status(
220 RTNLMessage::AddressStatus(address.prefix(), flags, scope));
221 return message;
222}
223
Chris Masone2aa97072011-08-09 17:35:08 -0700224void DeviceInfoTest::SendMessageToDeviceInfo(const RTNLMessage &message) {
Paul Stewart9a908082011-08-31 12:18:48 -0700225 if (message.type() == RTNLMessage::kTypeLink) {
226 device_info_.LinkMsgHandler(message);
227 } else if (message.type() == RTNLMessage::kTypeAddress) {
228 device_info_.AddressMsgHandler(message);
229 } else {
230 NOTREACHED();
231 }
232}
233
234MATCHER_P(IsIPAddress, address, "") {
235 // NB: IPAddress objects don't support the "==" operator as per style, so
236 // we need a custom matcher.
237 return address.Equals(arg);
Darin Petkov633ac6f2011-07-08 13:56:13 -0700238}
239
Paul Stewart8c116a92012-05-02 18:30:03 -0700240TEST_F(DeviceInfoTest, StartStop) {
241 EXPECT_FALSE(device_info_.link_listener_.get());
242 EXPECT_FALSE(device_info_.address_listener_.get());
243 EXPECT_TRUE(device_info_.infos_.empty());
244
245 EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestLink |
246 RTNLHandler::kRequestAddr));
Paul Stewart1ac4e842012-07-10 12:58:12 -0700247 EXPECT_CALL(dispatcher_, PostDelayedTask(
Ben Chanb061f892013-02-27 17:46:55 -0800248 _, DeviceInfo::kRequestLinkStatisticsIntervalMilliseconds));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700249 device_info_.Start();
Paul Stewart8c116a92012-05-02 18:30:03 -0700250 EXPECT_TRUE(device_info_.link_listener_.get());
251 EXPECT_TRUE(device_info_.address_listener_.get());
252 EXPECT_TRUE(device_info_.infos_.empty());
253 Mock::VerifyAndClearExpectations(&rtnl_handler_);
254
255 CreateInterfaceAddress();
256 EXPECT_FALSE(device_info_.infos_.empty());
257
258 device_info_.Stop();
259 EXPECT_FALSE(device_info_.link_listener_.get());
260 EXPECT_FALSE(device_info_.address_listener_.get());
261 EXPECT_TRUE(device_info_.infos_.empty());
262}
263
Paul Stewart1ac4e842012-07-10 12:58:12 -0700264TEST_F(DeviceInfoTest, RequestLinkStatistics) {
265 EXPECT_CALL(rtnl_handler_, RequestDump(RTNLHandler::kRequestLink));
266 EXPECT_CALL(dispatcher_, PostDelayedTask(
Ben Chanb061f892013-02-27 17:46:55 -0800267 _, DeviceInfo::kRequestLinkStatisticsIntervalMilliseconds));
Paul Stewart1ac4e842012-07-10 12:58:12 -0700268 device_info_.RequestLinkStatistics();
269}
270
Paul Stewart8c116a92012-05-02 18:30:03 -0700271TEST_F(DeviceInfoTest, DeviceEnumeration) {
Paul Stewart9a908082011-08-31 12:18:48 -0700272 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
Darin Petkove6193c02011-08-11 12:42:40 -0700273 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_LOWER_UP, 0));
274 EXPECT_FALSE(device_info_.GetDevice(kTestDeviceIndex).get());
Darin Petkovf8046b82012-04-24 16:29:23 +0200275 EXPECT_EQ(-1, device_info_.GetIndex(kTestDeviceName));
Darin Petkove6193c02011-08-11 12:42:40 -0700276 SendMessageToDeviceInfo(*message);
277 EXPECT_TRUE(device_info_.GetDevice(kTestDeviceIndex).get());
278 unsigned int flags = 0;
279 EXPECT_TRUE(device_info_.GetFlags(kTestDeviceIndex, &flags));
280 EXPECT_EQ(IFF_LOWER_UP, flags);
Darin Petkove3e1cfa2011-08-11 13:41:17 -0700281 ByteString address;
Paul Stewart32852962011-08-30 14:06:53 -0700282 EXPECT_TRUE(device_info_.GetMACAddress(kTestDeviceIndex, &address));
Darin Petkove3e1cfa2011-08-11 13:41:17 -0700283 EXPECT_FALSE(address.IsEmpty());
Paul Stewart9a908082011-08-31 12:18:48 -0700284 EXPECT_TRUE(address.Equals(ByteString(kTestMACAddress,
285 sizeof(kTestMACAddress))));
Darin Petkovf8046b82012-04-24 16:29:23 +0200286 EXPECT_EQ(kTestDeviceIndex, device_info_.GetIndex(kTestDeviceName));
Paul Stewarta3c56f92011-05-26 07:08:52 -0700287
Paul Stewart9a908082011-08-31 12:18:48 -0700288 message.reset(BuildLinkMessage(RTNLMessage::kModeAdd));
Darin Petkove6193c02011-08-11 12:42:40 -0700289 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_UP | IFF_RUNNING, 0));
290 SendMessageToDeviceInfo(*message);
291 EXPECT_TRUE(device_info_.GetFlags(kTestDeviceIndex, &flags));
292 EXPECT_EQ(IFF_UP | IFF_RUNNING, flags);
Paul Stewartb50f0b92011-05-16 16:31:42 -0700293
Paul Stewart9a908082011-08-31 12:18:48 -0700294 message.reset(BuildLinkMessage(RTNLMessage::kModeDelete));
Paul Stewart8c116a92012-05-02 18:30:03 -0700295 EXPECT_CALL(manager_, DeregisterDevice(_)).Times(1);
Darin Petkove6193c02011-08-11 12:42:40 -0700296 SendMessageToDeviceInfo(*message);
297 EXPECT_FALSE(device_info_.GetDevice(kTestDeviceIndex).get());
298 EXPECT_FALSE(device_info_.GetFlags(kTestDeviceIndex, NULL));
Darin Petkovf8046b82012-04-24 16:29:23 +0200299 EXPECT_EQ(-1, device_info_.GetIndex(kTestDeviceName));
Paul Stewart8c116a92012-05-02 18:30:03 -0700300}
Paul Stewarta3c56f92011-05-26 07:08:52 -0700301
Ben Chan5086b972013-01-15 21:51:38 -0800302TEST_F(DeviceInfoTest, GetUninitializedTechnologies) {
303 vector<string> technologies = device_info_.GetUninitializedTechnologies();
304 set<string> expected_technologies;
305
306 EXPECT_THAT(set<string>(technologies.begin(), technologies.end()),
307 ContainerEq(expected_technologies));
308
309 device_info_.infos_[0].technology = Technology::kUnknown;
310 EXPECT_THAT(set<string>(technologies.begin(), technologies.end()),
311 ContainerEq(expected_technologies));
312
313 device_info_.infos_[1].technology = Technology::kCellular;
314 technologies = device_info_.GetUninitializedTechnologies();
315 expected_technologies.insert(Technology::NameFromIdentifier(
316 Technology::kCellular));
317 EXPECT_THAT(set<string>(technologies.begin(), technologies.end()),
318 ContainerEq(expected_technologies));
319
320 device_info_.infos_[2].technology = Technology::kWiMax;
321 technologies = device_info_.GetUninitializedTechnologies();
322 expected_technologies.insert(Technology::NameFromIdentifier(
323 Technology::kWiMax));
324 EXPECT_THAT(set<string>(technologies.begin(), technologies.end()),
325 ContainerEq(expected_technologies));
326
327 scoped_refptr<MockDevice> device(new MockDevice(
328 &control_interface_, &dispatcher_, &metrics_, &manager_,
329 "null0", "addr0", 1));
330 device_info_.infos_[1].device = device;
331 technologies = device_info_.GetUninitializedTechnologies();
332 expected_technologies.erase(Technology::NameFromIdentifier(
333 Technology::kCellular));
334 EXPECT_THAT(set<string>(technologies.begin(), technologies.end()),
335 ContainerEq(expected_technologies));
336
337 device_info_.infos_[3].technology = Technology::kCellular;
338 technologies = device_info_.GetUninitializedTechnologies();
Arman Ugurayb00c13d2013-07-29 18:20:52 -0700339 EXPECT_THAT(set<string>(technologies.begin(), technologies.end()),
340 ContainerEq(expected_technologies));
341
342 device_info_.infos_[3].device = device;
343 device_info_.infos_[1].device = NULL;
344 technologies = device_info_.GetUninitializedTechnologies();
Ben Chan5086b972013-01-15 21:51:38 -0800345 EXPECT_THAT(set<string>(technologies.begin(), technologies.end()),
346 ContainerEq(expected_technologies));
347}
348
Paul Stewart1ac4e842012-07-10 12:58:12 -0700349TEST_F(DeviceInfoTest, GetByteCounts) {
350 uint64 rx_bytes, tx_bytes;
351 EXPECT_FALSE(device_info_.GetByteCounts(
352 kTestDeviceIndex, &rx_bytes, &tx_bytes));
353
354 // No link statistics in the message.
355 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
356 SendMessageToDeviceInfo(*message);
357 EXPECT_TRUE(device_info_.GetByteCounts(
358 kTestDeviceIndex, &rx_bytes, &tx_bytes));
359 EXPECT_EQ(0, rx_bytes);
360 EXPECT_EQ(0, tx_bytes);
361
362 // Short link statistics message.
363 message.reset(BuildLinkMessage(RTNLMessage::kModeAdd));
364 struct rtnl_link_stats64 stats;
365 memset(&stats, 0, sizeof(stats));
366 stats.rx_bytes = kReceiveByteCount;
367 stats.tx_bytes = kTransmitByteCount;
368 ByteString stats_bytes0(reinterpret_cast<const unsigned char*>(&stats),
369 sizeof(stats) - 1);
370 message->SetAttribute(IFLA_STATS64, stats_bytes0);
371 SendMessageToDeviceInfo(*message);
372 EXPECT_TRUE(device_info_.GetByteCounts(
373 kTestDeviceIndex, &rx_bytes, &tx_bytes));
374 EXPECT_EQ(0, rx_bytes);
375 EXPECT_EQ(0, tx_bytes);
376
377 // Correctly sized link statistics message.
378 message.reset(BuildLinkMessage(RTNLMessage::kModeAdd));
379 ByteString stats_bytes1(reinterpret_cast<const unsigned char*>(&stats),
380 sizeof(stats));
381 message->SetAttribute(IFLA_STATS64, stats_bytes1);
382 SendMessageToDeviceInfo(*message);
383 EXPECT_TRUE(device_info_.GetByteCounts(
384 kTestDeviceIndex, &rx_bytes, &tx_bytes));
385 EXPECT_EQ(kReceiveByteCount, rx_bytes);
386 EXPECT_EQ(kTransmitByteCount, tx_bytes);
387}
388
Paul Stewart8c116a92012-05-02 18:30:03 -0700389TEST_F(DeviceInfoTest, CreateDeviceCellular) {
390 IPAddress address = CreateInterfaceAddress();
391
392 // A cellular device should be offered to ModemInfo.
393 StrictMock<MockModemInfo> modem_info;
394 EXPECT_CALL(manager_, modem_info()).WillOnce(Return(&modem_info));
395 EXPECT_CALL(modem_info, OnDeviceInfoAvailable(kTestDeviceName)).Times(1);
396 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
397 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
398 IsIPAddress(address)));
399 EXPECT_FALSE(CreateDevice(
400 kTestDeviceName, "address", kTestDeviceIndex, Technology::kCellular));
401}
402
Darin Petkove4b27022012-05-16 13:28:50 +0200403TEST_F(DeviceInfoTest, CreateDeviceWiMax) {
404 IPAddress address = CreateInterfaceAddress();
405
406 // A WiMax device should be offered to WiMaxProvider.
407 StrictMock<MockWiMaxProvider> wimax_provider;
408 EXPECT_CALL(manager_, wimax_provider()).WillOnce(Return(&wimax_provider));
409 EXPECT_CALL(wimax_provider, OnDeviceInfoAvailable(kTestDeviceName)).Times(1);
410 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
411 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
412 IsIPAddress(address)));
Ben Chan4b285862012-10-10 22:52:16 -0700413 device_info_.infos_[kTestDeviceIndex].mac_address =
414 ByteString(kTestMACAddress, sizeof(kTestMACAddress));
Darin Petkove4b27022012-05-16 13:28:50 +0200415 EXPECT_FALSE(CreateDevice(
416 kTestDeviceName, "address", kTestDeviceIndex, Technology::kWiMax));
Ben Chan4b285862012-10-10 22:52:16 -0700417 // The MAC address is clear such that it is obtained via
418 // GetMACAddressFromKernel() instead.
419 EXPECT_TRUE(device_info_.infos_[kTestDeviceIndex].mac_address.IsEmpty());
Darin Petkove4b27022012-05-16 13:28:50 +0200420}
421
Paul Stewart8c116a92012-05-02 18:30:03 -0700422TEST_F(DeviceInfoTest, CreateDeviceEthernet) {
423 IPAddress address = CreateInterfaceAddress();
424
425 // An Ethernet device should cause routes and addresses to be flushed.
426 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
427 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
428 IsIPAddress(address)));
429 DeviceRefPtr device = CreateDevice(
430 kTestDeviceName, "address", kTestDeviceIndex, Technology::kEthernet);
431 EXPECT_TRUE(device);
432 Mock::VerifyAndClearExpectations(&routing_table_);
433 Mock::VerifyAndClearExpectations(&rtnl_handler_);
434
435 // The Ethernet device destructor notifies the manager.
436 EXPECT_CALL(manager_, UpdateEnabledTechnologies()).Times(1);
437 device = NULL;
438}
439
440TEST_F(DeviceInfoTest, CreateDeviceVirtioEthernet) {
441 IPAddress address = CreateInterfaceAddress();
442
443 // VirtioEthernet is identical to Ethernet from the perspective of this test.
444 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
445 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
446 IsIPAddress(address)));
447 DeviceRefPtr device = CreateDevice(
448 kTestDeviceName, "address", kTestDeviceIndex,
449 Technology::kVirtioEthernet);
450 EXPECT_TRUE(device);
451 Mock::VerifyAndClearExpectations(&routing_table_);
452 Mock::VerifyAndClearExpectations(&rtnl_handler_);
453
454 // The Ethernet device destructor notifies the manager.
455 EXPECT_CALL(manager_, UpdateEnabledTechnologies()).Times(1);
456 device = NULL;
457}
458
Paul Stewart2ddf2c62013-04-16 09:47:34 -0700459MATCHER_P(IsGetInterfaceMessage, index, "") {
460 if (arg->message_type() != Nl80211Message::GetMessageType()) {
461 return false;
462 }
463 const Nl80211Message *msg = reinterpret_cast<const Nl80211Message *>(arg);
464 if (msg->command() != NL80211_CMD_GET_INTERFACE) {
465 return false;
466 }
467 uint32_t interface_index;
468 if (!msg->const_attributes()->GetU32AttributeValue(NL80211_ATTR_IFINDEX,
469 &interface_index)) {
470 return false;
471 }
472 // kInterfaceIndex is signed, but the attribute as handed from the kernel
473 // is unsigned. We're silently casting it away with this assignment.
474 uint32_t test_interface_index = index;
475 return interface_index == test_interface_index;
476}
477
Paul Stewart8c116a92012-05-02 18:30:03 -0700478TEST_F(DeviceInfoTest, CreateDeviceWiFi) {
479 IPAddress address = CreateInterfaceAddress();
480
481 // WiFi looks a lot like Ethernet too.
Paul Stewart2ddf2c62013-04-16 09:47:34 -0700482 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex));
Paul Stewart8c116a92012-05-02 18:30:03 -0700483 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
484 IsIPAddress(address)));
Paul Stewart2ddf2c62013-04-16 09:47:34 -0700485
486 // Set the nl80211 message type to some non-default value.
487 Nl80211Message::SetMessageType(1234);
488
Wade Guthrie7347bf22013-04-30 11:21:51 -0700489 EXPECT_CALL(
490 netlink_manager_,
491 SendNl80211Message(IsGetInterfaceMessage(kTestDeviceIndex), _, _));
Paul Stewart2ddf2c62013-04-16 09:47:34 -0700492 EXPECT_FALSE(CreateDevice(
Paul Stewart8c116a92012-05-02 18:30:03 -0700493 kTestDeviceName, "address", kTestDeviceIndex, Technology::kWifi));
494}
495
496TEST_F(DeviceInfoTest, CreateDeviceTunnelAccepted) {
497 IPAddress address = CreateInterfaceAddress();
498
499 // A VPN device should be offered to VPNProvider.
Darin Petkovc3505a52013-03-18 15:13:29 +0100500 MockVPNProvider *vpn_provider = new StrictMock<MockVPNProvider>;
501 SetVPNProvider(vpn_provider);
502 EXPECT_CALL(*vpn_provider,
Paul Stewart8c116a92012-05-02 18:30:03 -0700503 OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
504 .WillOnce(Return(true));
505 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
506 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
507 IsIPAddress(address)));
508 EXPECT_CALL(rtnl_handler_, RemoveInterface(_)).Times(0);
509 EXPECT_FALSE(CreateDevice(
510 kTestDeviceName, "address", kTestDeviceIndex, Technology::kTunnel));
511}
512
513TEST_F(DeviceInfoTest, CreateDeviceTunnelRejected) {
514 IPAddress address = CreateInterfaceAddress();
515
516 // A VPN device should be offered to VPNProvider.
Darin Petkovc3505a52013-03-18 15:13:29 +0100517 MockVPNProvider *vpn_provider = new StrictMock<MockVPNProvider>;
518 SetVPNProvider(vpn_provider);
519 EXPECT_CALL(*vpn_provider,
Paul Stewart8c116a92012-05-02 18:30:03 -0700520 OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
521 .WillOnce(Return(false));
522 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
523 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
524 IsIPAddress(address)));
525 // Since the device was rejected by the VPNProvider, DeviceInfo will
526 // remove the interface.
527 EXPECT_CALL(rtnl_handler_, RemoveInterface(kTestDeviceIndex)).Times(1);
528 EXPECT_FALSE(CreateDevice(
529 kTestDeviceName, "address", kTestDeviceIndex, Technology::kTunnel));
530}
531
532TEST_F(DeviceInfoTest, CreateDevicePPP) {
533 IPAddress address = CreateInterfaceAddress();
534
535 // A VPN device should be offered to VPNProvider.
Darin Petkovc3505a52013-03-18 15:13:29 +0100536 MockVPNProvider *vpn_provider = new StrictMock<MockVPNProvider>;
537 SetVPNProvider(vpn_provider);
538 EXPECT_CALL(*vpn_provider,
Paul Stewart8c116a92012-05-02 18:30:03 -0700539 OnDeviceInfoAvailable(kTestDeviceName, kTestDeviceIndex))
540 .WillOnce(Return(false));
541 EXPECT_CALL(routing_table_, FlushRoutes(kTestDeviceIndex)).Times(1);
542 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
543 IsIPAddress(address)));
544 // We do not remove PPP interfaces even if the provider does not accept it.
545 EXPECT_CALL(rtnl_handler_, RemoveInterface(_)).Times(0);
546 EXPECT_FALSE(CreateDevice(
547 kTestDeviceName, "address", kTestDeviceIndex, Technology::kPPP));
548}
549
550TEST_F(DeviceInfoTest, CreateDeviceLoopback) {
551 // A loopback device should be brought up, and nothing else done to it.
552 EXPECT_CALL(routing_table_, FlushRoutes(_)).Times(0);
553 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(_, _)).Times(0);
554 EXPECT_CALL(rtnl_handler_,
555 SetInterfaceFlags(kTestDeviceIndex, IFF_UP, IFF_UP)).Times(1);
556 EXPECT_FALSE(CreateDevice(
557 kTestDeviceName, "address", kTestDeviceIndex, Technology::kLoopback));
558}
559
Paul Stewart050cfc02012-07-06 20:38:54 -0700560TEST_F(DeviceInfoTest, CreateDeviceCDCEthernet) {
Ben Chan4eb4ddf2013-06-20 22:16:56 -0700561 // A cdc_ether / cdc_ncm device should be postponed to a task.
Paul Stewart050cfc02012-07-06 20:38:54 -0700562 EXPECT_CALL(manager_, modem_info()).Times(0);
563 EXPECT_CALL(routing_table_, FlushRoutes(_)).Times(0);
564 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(_, _)).Times(0);
565 EXPECT_CALL(dispatcher_,
Paul Stewart1ac4e842012-07-10 12:58:12 -0700566 PostDelayedTask(_, GetDelayedDeviceCreationMilliseconds()));
Paul Stewart050cfc02012-07-06 20:38:54 -0700567 EXPECT_TRUE(GetDelayedDevices().empty());
568 EXPECT_FALSE(CreateDevice(
569 kTestDeviceName, "address", kTestDeviceIndex, Technology::kCDCEthernet));
570 EXPECT_FALSE(GetDelayedDevices().empty());
571 EXPECT_EQ(1, GetDelayedDevices().size());
572 EXPECT_EQ(kTestDeviceIndex, *GetDelayedDevices().begin());
573}
574
Paul Stewart8c116a92012-05-02 18:30:03 -0700575TEST_F(DeviceInfoTest, CreateDeviceUnknown) {
576 IPAddress address = CreateInterfaceAddress();
577
578 // An unknown (blacklisted, unhandled, etc) device won't be flushed or
579 // registered.
580 EXPECT_CALL(routing_table_, FlushRoutes(_)).Times(0);
581 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(_, _)).Times(0);
582 EXPECT_TRUE(CreateDevice(
583 kTestDeviceName, "address", kTestDeviceIndex, Technology::kUnknown));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700584}
585
mukesh agrawal8f317b62011-07-15 11:53:23 -0700586TEST_F(DeviceInfoTest, DeviceBlackList) {
587 device_info_.AddDeviceToBlackList(kTestDeviceName);
Paul Stewart9a908082011-08-31 12:18:48 -0700588 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
Darin Petkove6193c02011-08-11 12:42:40 -0700589 SendMessageToDeviceInfo(*message);
mukesh agrawal8f317b62011-07-15 11:53:23 -0700590
Darin Petkove6193c02011-08-11 12:42:40 -0700591 DeviceRefPtr device = device_info_.GetDevice(kTestDeviceIndex);
592 ASSERT_TRUE(device.get());
Joshua Krollda798622012-06-05 12:30:48 -0700593 EXPECT_TRUE(device->technology() == Technology::kBlacklisted);
mukesh agrawal8f317b62011-07-15 11:53:23 -0700594}
595
Paul Stewart9a908082011-08-31 12:18:48 -0700596TEST_F(DeviceInfoTest, DeviceAddressList) {
Paul Stewart9a908082011-08-31 12:18:48 -0700597 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
598 SendMessageToDeviceInfo(*message);
599
600 vector<DeviceInfo::AddressData> addresses;
601 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
602 EXPECT_TRUE(addresses.empty());
603
604 // Add an address to the device address list
Paul Stewart7355ce12011-09-02 10:47:01 -0700605 IPAddress ip_address0(IPAddress::kFamilyIPv4);
Paul Stewart9a908082011-08-31 12:18:48 -0700606 EXPECT_TRUE(ip_address0.SetAddressFromString(kTestIPAddress0));
607 ip_address0.set_prefix(kTestIPAddressPrefix0);
608 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address0, 0, 0));
609 SendMessageToDeviceInfo(*message);
610 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
611 EXPECT_EQ(1, addresses.size());
612 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
613
614 // Re-adding the same address shouldn't cause the address list to change
615 SendMessageToDeviceInfo(*message);
616 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
617 EXPECT_EQ(1, addresses.size());
618 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
619
620 // Adding a new address should expand the list
Paul Stewart7355ce12011-09-02 10:47:01 -0700621 IPAddress ip_address1(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700622 EXPECT_TRUE(ip_address1.SetAddressFromString(kTestIPAddress1));
623 ip_address1.set_prefix(kTestIPAddressPrefix1);
624 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address1, 0, 0));
625 SendMessageToDeviceInfo(*message);
626 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
627 EXPECT_EQ(2, addresses.size());
628 EXPECT_TRUE(ip_address0.Equals(addresses[0].address));
629 EXPECT_TRUE(ip_address1.Equals(addresses[1].address));
630
631 // Deleting an address should reduce the list
632 message.reset(BuildAddressMessage(RTNLMessage::kModeDelete,
633 ip_address0,
634 0,
635 0));
636 SendMessageToDeviceInfo(*message);
637 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
638 EXPECT_EQ(1, addresses.size());
639 EXPECT_TRUE(ip_address1.Equals(addresses[0].address));
640
641 // Delete last item
642 message.reset(BuildAddressMessage(RTNLMessage::kModeDelete,
643 ip_address1,
644 0,
645 0));
646 SendMessageToDeviceInfo(*message);
647 EXPECT_TRUE(device_info_.GetAddresses(kTestDeviceIndex, &addresses));
648 EXPECT_TRUE(addresses.empty());
649
650 // Delete device
651 message.reset(BuildLinkMessage(RTNLMessage::kModeDelete));
Paul Stewart8c116a92012-05-02 18:30:03 -0700652 EXPECT_CALL(manager_, DeregisterDevice(_)).Times(1);
Paul Stewart9a908082011-08-31 12:18:48 -0700653 SendMessageToDeviceInfo(*message);
654
655 // Should be able to handle message for interface that doesn't exist
656 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd, ip_address0, 0, 0));
657 SendMessageToDeviceInfo(*message);
658 EXPECT_FALSE(device_info_.GetDevice(kTestDeviceIndex).get());
Paul Stewart9a908082011-08-31 12:18:48 -0700659}
660
661TEST_F(DeviceInfoTest, FlushAddressList) {
Paul Stewart9a908082011-08-31 12:18:48 -0700662 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
663 SendMessageToDeviceInfo(*message);
664
Paul Stewart7355ce12011-09-02 10:47:01 -0700665 IPAddress address1(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700666 EXPECT_TRUE(address1.SetAddressFromString(kTestIPAddress1));
667 address1.set_prefix(kTestIPAddressPrefix1);
668 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
669 address1,
670 0,
671 RT_SCOPE_UNIVERSE));
672 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700673 IPAddress address2(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700674 EXPECT_TRUE(address2.SetAddressFromString(kTestIPAddress2));
675 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
676 address2,
677 IFA_F_TEMPORARY,
678 RT_SCOPE_UNIVERSE));
679 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700680 IPAddress address3(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700681 EXPECT_TRUE(address3.SetAddressFromString(kTestIPAddress3));
682 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
683 address3,
684 0,
685 RT_SCOPE_LINK));
686 SendMessageToDeviceInfo(*message);
Paul Stewart7355ce12011-09-02 10:47:01 -0700687 IPAddress address4(IPAddress::kFamilyIPv6);
Paul Stewart9a908082011-08-31 12:18:48 -0700688 EXPECT_TRUE(address4.SetAddressFromString(kTestIPAddress4));
689 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
690 address4,
691 IFA_F_PERMANENT,
692 RT_SCOPE_UNIVERSE));
693 SendMessageToDeviceInfo(*message);
694
695 // DeviceInfo now has 4 addresses associated with it, but only two of
696 // them are valid for flush.
697 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
698 IsIPAddress(address1)));
699 EXPECT_CALL(rtnl_handler_, RemoveInterfaceAddress(kTestDeviceIndex,
700 IsIPAddress(address2)));
701 device_info_.FlushAddresses(kTestDeviceIndex);
Paul Stewart9a908082011-08-31 12:18:48 -0700702}
703
Paul Stewart05a42c22012-08-02 16:47:21 -0700704TEST_F(DeviceInfoTest, HasOtherAddress) {
705 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
706 SendMessageToDeviceInfo(*message);
707
708 IPAddress address0(IPAddress::kFamilyIPv4);
709 EXPECT_TRUE(address0.SetAddressFromString(kTestIPAddress0));
710
711 // There are no addresses on this interface.
712 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address0));
713
714 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
715 address0,
716 0,
717 RT_SCOPE_UNIVERSE));
718 SendMessageToDeviceInfo(*message);
719
720 IPAddress address1(IPAddress::kFamilyIPv6);
721 EXPECT_TRUE(address1.SetAddressFromString(kTestIPAddress1));
722 address1.set_prefix(kTestIPAddressPrefix1);
723 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
724 address1,
725 0,
726 RT_SCOPE_LINK));
727 SendMessageToDeviceInfo(*message);
728
729 IPAddress address2(IPAddress::kFamilyIPv6);
730 EXPECT_TRUE(address2.SetAddressFromString(kTestIPAddress2));
731 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
732 address2,
733 IFA_F_TEMPORARY,
734 RT_SCOPE_UNIVERSE));
735 SendMessageToDeviceInfo(*message);
736
737 IPAddress address3(IPAddress::kFamilyIPv6);
738 EXPECT_TRUE(address3.SetAddressFromString(kTestIPAddress3));
739
740 // The only IPv6 addresses on this interface are either flagged as
741 // temporary, or they are not universally scoped.
742 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address3));
743
744
745 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
746 address3,
747 0,
748 RT_SCOPE_UNIVERSE));
749 SendMessageToDeviceInfo(*message);
750
751 // address0 is on this interface.
752 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address0));
753 // address1 is on this interface.
754 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address1));
755 // address2 is on this interface.
756 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address2));
757 // address3 is on this interface.
758 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address3));
759
760 IPAddress address4(IPAddress::kFamilyIPv6);
761 EXPECT_TRUE(address4.SetAddressFromString(kTestIPAddress4));
762
763 // address4 is not on this interface, but address3 is, and is a qualified
764 // IPv6 address.
765 EXPECT_TRUE(device_info_.HasOtherAddress(kTestDeviceIndex, address4));
766
767 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
768 address4,
769 IFA_F_PERMANENT,
770 RT_SCOPE_UNIVERSE));
771 SendMessageToDeviceInfo(*message);
772
773 // address4 is now on this interface.
774 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address4));
775
776 IPAddress address5(IPAddress::kFamilyIPv4);
777 EXPECT_TRUE(address5.SetAddressFromString(kTestIPAddress5));
778 // address5 is not on this interface, but address0 is.
779 EXPECT_TRUE(device_info_.HasOtherAddress(kTestDeviceIndex, address5));
780
781 message.reset(BuildAddressMessage(RTNLMessage::kModeAdd,
782 address5,
783 IFA_F_PERMANENT,
784 RT_SCOPE_UNIVERSE));
785 SendMessageToDeviceInfo(*message);
786
787 // address5 is now on this interface.
788 EXPECT_FALSE(device_info_.HasOtherAddress(kTestDeviceIndex, address5));
789}
790
Thieu Leb27beee2012-04-20 09:19:06 -0700791TEST_F(DeviceInfoTest, HasSubdir) {
Paul Stewart5ad16062013-02-21 18:10:48 -0800792 base::ScopedTempDir temp_dir;
Thieu Le8f1c8352012-04-16 11:02:12 -0700793 EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
Thieu Leb27beee2012-04-20 09:19:06 -0700794 EXPECT_TRUE(file_util::CreateDirectory(temp_dir.path().Append("child1")));
795 FilePath child2 = temp_dir.path().Append("child2");
796 EXPECT_TRUE(file_util::CreateDirectory(child2));
797 FilePath grandchild = child2.Append("grandchild");
Thieu Le8f1c8352012-04-16 11:02:12 -0700798 EXPECT_TRUE(file_util::CreateDirectory(grandchild));
799 EXPECT_TRUE(file_util::CreateDirectory(grandchild.Append("greatgrandchild")));
Thieu Leb27beee2012-04-20 09:19:06 -0700800 EXPECT_TRUE(DeviceInfo::HasSubdir(temp_dir.path(),
801 FilePath("grandchild")));
802 EXPECT_TRUE(DeviceInfo::HasSubdir(temp_dir.path(),
803 FilePath("greatgrandchild")));
804 EXPECT_FALSE(DeviceInfo::HasSubdir(temp_dir.path(),
805 FilePath("nonexistent")));
Thieu Le8f1c8352012-04-16 11:02:12 -0700806}
807
Gary Morain41780232012-07-31 15:08:31 -0700808TEST_F(DeviceInfoTest, GetMACAddressFromKernelUnknownDevice) {
809 SetSockets();
810 EXPECT_CALL(*mock_sockets_, Socket(PF_INET, SOCK_DGRAM, 0)).Times(0);
811 ByteString mac_address =
812 device_info_.GetMACAddressFromKernel(kTestDeviceIndex);
813 EXPECT_TRUE(mac_address.IsEmpty());
814}
815
816TEST_F(DeviceInfoTest, GetMACAddressFromKernelUnableToOpenSocket) {
817 SetSockets();
818 EXPECT_CALL(*mock_sockets_, Socket(PF_INET, SOCK_DGRAM, 0))
819 .WillOnce(Return(-1));
820 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
821 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_LOWER_UP, 0));
822 SendMessageToDeviceInfo(*message);
823 EXPECT_TRUE(device_info_.GetDevice(kTestDeviceIndex).get());
824 ByteString mac_address =
825 device_info_.GetMACAddressFromKernel(kTestDeviceIndex);
826 EXPECT_TRUE(mac_address.IsEmpty());
827}
828
829TEST_F(DeviceInfoTest, GetMACAddressFromKernelIoctlFails) {
830 SetSockets();
831 const int kFd = 99;
832 EXPECT_CALL(*mock_sockets_, Socket(PF_INET, SOCK_DGRAM, 0))
833 .WillOnce(Return(kFd));
834 EXPECT_CALL(*mock_sockets_, Ioctl(kFd, SIOCGIFHWADDR, NotNull()))
835 .WillOnce(Return(-1));
836 EXPECT_CALL(*mock_sockets_, Close(kFd));
837
838 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
839 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_LOWER_UP, 0));
840 SendMessageToDeviceInfo(*message);
841 EXPECT_TRUE(device_info_.GetDevice(kTestDeviceIndex).get());
842
843 ByteString mac_address =
844 device_info_.GetMACAddressFromKernel(kTestDeviceIndex);
845 EXPECT_TRUE(mac_address.IsEmpty());
846}
847
848MATCHER_P2(IfreqEquals, ifindex, ifname, "") {
849 const struct ifreq *const ifr = static_cast<struct ifreq *>(arg);
850 return (ifr != NULL) &&
851 (ifr->ifr_ifindex == ifindex) &&
852 (strcmp(ifname, ifr->ifr_name) == 0);
853}
854
855ACTION_P(SetIfreq, ifr) {
856 struct ifreq *const ifr_arg = static_cast<struct ifreq *>(arg2);
857 *ifr_arg = ifr;
858}
859
860TEST_F(DeviceInfoTest, GetMACAddressFromKernel) {
861 SetSockets();
862 const int kFd = 99;
863 struct ifreq ifr;
Han Shenfc349252012-08-30 11:36:04 -0700864 static uint8_t kMacAddress[] = {0x00, 0x01, 0x02, 0xaa, 0xbb, 0xcc};
Gary Morain41780232012-07-31 15:08:31 -0700865 memcpy(ifr.ifr_hwaddr.sa_data, kMacAddress, sizeof(kMacAddress));
866 EXPECT_CALL(*mock_sockets_, Socket(PF_INET, SOCK_DGRAM, 0))
867 .WillOnce(Return(kFd));
868 EXPECT_CALL(*mock_sockets_,
869 Ioctl(kFd, SIOCGIFHWADDR,
870 IfreqEquals(kTestDeviceIndex, kTestDeviceName)))
871 .WillOnce(DoAll(SetIfreq(ifr), Return(0)));
872 EXPECT_CALL(*mock_sockets_, Close(kFd));
873
874 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
875 message->set_link_status(RTNLMessage::LinkStatus(0, IFF_LOWER_UP, 0));
876 SendMessageToDeviceInfo(*message);
877 EXPECT_TRUE(device_info_.GetDevice(kTestDeviceIndex).get());
878
879 ByteString mac_address =
880 device_info_.GetMACAddressFromKernel(kTestDeviceIndex);
881 EXPECT_THAT(kMacAddress,
882 ElementsAreArray(mac_address.GetData(), sizeof(kMacAddress)));
883}
884
Paul Stewartca876ee2012-04-21 08:55:58 -0700885class DeviceInfoTechnologyTest : public DeviceInfoTest {
886 public:
Jason Glasgowabc54032012-04-20 16:08:32 -0400887 DeviceInfoTechnologyTest()
888 : DeviceInfoTest(),
889 test_device_name_(kTestDeviceName) {}
Paul Stewartca876ee2012-04-21 08:55:58 -0700890 virtual ~DeviceInfoTechnologyTest() {}
891
892 virtual void SetUp() {
893 temp_dir_.CreateUniqueTempDir();
894 device_info_root_ = temp_dir_.path().Append("sys/class/net");
895 device_info_.device_info_root_ = device_info_root_;
896 // Most tests require that the uevent file exist.
897 CreateInfoFile("uevent", "xxx");
898 }
899
900 Technology::Identifier GetDeviceTechnology() {
Jason Glasgowabc54032012-04-20 16:08:32 -0400901 return device_info_.GetDeviceTechnology(test_device_name_);
Paul Stewartca876ee2012-04-21 08:55:58 -0700902 }
903 FilePath GetInfoPath(const string &name);
904 void CreateInfoFile(const string &name, const string &contents);
905 void CreateInfoSymLink(const string &name, const string &contents);
Jason Glasgowabc54032012-04-20 16:08:32 -0400906 void SetDeviceName(const string &name) {
907 test_device_name_ = name;
908 SetUp();
909 }
Paul Stewartca876ee2012-04-21 08:55:58 -0700910
911 protected:
Paul Stewart5ad16062013-02-21 18:10:48 -0800912 base::ScopedTempDir temp_dir_;
Paul Stewartca876ee2012-04-21 08:55:58 -0700913 FilePath device_info_root_;
Jason Glasgowabc54032012-04-20 16:08:32 -0400914 string test_device_name_;
Paul Stewartca876ee2012-04-21 08:55:58 -0700915};
916
917FilePath DeviceInfoTechnologyTest::GetInfoPath(const string &name) {
Jason Glasgowabc54032012-04-20 16:08:32 -0400918 return device_info_root_.Append(test_device_name_).Append(name);
Paul Stewartca876ee2012-04-21 08:55:58 -0700919}
920
921void DeviceInfoTechnologyTest::CreateInfoFile(const string &name,
922 const string &contents) {
923 FilePath info_path = GetInfoPath(name);
924 EXPECT_TRUE(file_util::CreateDirectory(info_path.DirName()));
925 string contents_newline(contents + "\n");
926 EXPECT_TRUE(file_util::WriteFile(info_path, contents_newline.c_str(),
927 contents_newline.size()));
928}
929
930void DeviceInfoTechnologyTest::CreateInfoSymLink(const string &name,
931 const string &contents) {
932 FilePath info_path = GetInfoPath(name);
Paul Stewartca876ee2012-04-21 08:55:58 -0700933 EXPECT_TRUE(file_util::CreateDirectory(info_path.DirName()));
934 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath(contents), info_path));
935}
936
937TEST_F(DeviceInfoTechnologyTest, Unknown) {
938 EXPECT_EQ(Technology::kUnknown, GetDeviceTechnology());
939 // Should still be unknown even without a uevent file.
Ben Chan4eb4ddf2013-06-20 22:16:56 -0700940 EXPECT_TRUE(file_util::Delete(GetInfoPath("uevent"), false));
Paul Stewartca876ee2012-04-21 08:55:58 -0700941 EXPECT_EQ(Technology::kUnknown, GetDeviceTechnology());
942}
943
944TEST_F(DeviceInfoTechnologyTest, Loopback) {
945 CreateInfoFile("type", base::IntToString(ARPHRD_LOOPBACK));
946 EXPECT_EQ(Technology::kLoopback, GetDeviceTechnology());
947}
948
949TEST_F(DeviceInfoTechnologyTest, PPP) {
950 CreateInfoFile("type", base::IntToString(ARPHRD_PPP));
951 EXPECT_EQ(Technology::kPPP, GetDeviceTechnology());
952}
953
954TEST_F(DeviceInfoTechnologyTest, Tunnel) {
955 CreateInfoFile("tun_flags", base::IntToString(IFF_TUN));
956 EXPECT_EQ(Technology::kTunnel, GetDeviceTechnology());
957}
958
959TEST_F(DeviceInfoTechnologyTest, WiFi) {
960 CreateInfoFile("uevent", "DEVTYPE=wlan");
961 EXPECT_EQ(Technology::kWifi, GetDeviceTechnology());
962 CreateInfoFile("uevent", "foo\nDEVTYPE=wlan");
963 EXPECT_EQ(Technology::kWifi, GetDeviceTechnology());
964 CreateInfoFile("type", base::IntToString(ARPHRD_IEEE80211_RADIOTAP));
965 EXPECT_EQ(Technology::kWiFiMonitor, GetDeviceTechnology());
966}
967
968TEST_F(DeviceInfoTechnologyTest, Ethernet) {
969 CreateInfoSymLink("device/driver", "xxx");
970 EXPECT_EQ(Technology::kEthernet, GetDeviceTechnology());
971}
972
Darin Petkove4b27022012-05-16 13:28:50 +0200973TEST_F(DeviceInfoTechnologyTest, WiMax) {
974 CreateInfoSymLink("device/driver", "gdm_wimax");
975 EXPECT_EQ(Technology::kWiMax, GetDeviceTechnology());
976}
977
Paul Stewartca876ee2012-04-21 08:55:58 -0700978TEST_F(DeviceInfoTechnologyTest, CellularGobi1) {
979 CreateInfoSymLink("device/driver", "blah/foo/gobi");
980 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
981}
982
983TEST_F(DeviceInfoTechnologyTest, CellularGobi2) {
984 CreateInfoSymLink("device/driver", "../GobiNet");
985 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
986}
987
988TEST_F(DeviceInfoTechnologyTest, QCUSB) {
989 CreateInfoSymLink("device/driver", "QCUSBNet2k");
990 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
991}
992
Ben Chan0f90e0b2013-06-26 23:37:16 -0700993TEST_F(DeviceInfoTechnologyTest, CellularCdcMbim) {
994 CreateInfoSymLink("device/driver", "cdc_mbim");
995 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
996}
997
Ben Chan226d46a2012-10-11 00:22:17 -0700998TEST_F(DeviceInfoTechnologyTest, CellularQmiWwan) {
999 CreateInfoSymLink("device/driver", "qmi_wwan");
1000 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
1001}
1002
Paul Stewartca876ee2012-04-21 08:55:58 -07001003// Modem with absolute driver path with top-level tty file:
1004// /sys/class/net/dev0/device -> /sys/devices/virtual/0/00
Ben Chan4eb4ddf2013-06-20 22:16:56 -07001005// /sys/devices/virtual/0/00/driver -> /drivers/cdc_ether or /drivers/cdc_ncm
Paul Stewartca876ee2012-04-21 08:55:58 -07001006// /sys/devices/virtual/0/01/tty [empty directory]
Ben Chan4eb4ddf2013-06-20 22:16:56 -07001007TEST_F(DeviceInfoTechnologyTest, CDCEthernetModem1) {
Paul Stewartca876ee2012-04-21 08:55:58 -07001008 FilePath device_root(temp_dir_.path().Append("sys/devices/virtual/0"));
1009 FilePath device_path(device_root.Append("00"));
Ben Chan4eb4ddf2013-06-20 22:16:56 -07001010 FilePath driver_symlink(device_path.Append("driver"));
Paul Stewartca876ee2012-04-21 08:55:58 -07001011 EXPECT_TRUE(file_util::CreateDirectory(device_path));
1012 CreateInfoSymLink("device", device_path.value());
1013 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
Ben Chan4eb4ddf2013-06-20 22:16:56 -07001014 driver_symlink));
Paul Stewartca876ee2012-04-21 08:55:58 -07001015 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/tty")));
1016 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
Ben Chan4eb4ddf2013-06-20 22:16:56 -07001017
1018 EXPECT_TRUE(file_util::Delete(driver_symlink, false));
1019 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ncm"),
1020 driver_symlink));
1021 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
Paul Stewartca876ee2012-04-21 08:55:58 -07001022}
1023
1024// Modem with relative driver path with top-level tty file.
1025// /sys/class/net/dev0/device -> ../../../device_dir/0/00
Ben Chan4eb4ddf2013-06-20 22:16:56 -07001026// /sys/device_dir/0/00/driver -> /drivers/cdc_ether or /drivers/cdc_ncm
Paul Stewartca876ee2012-04-21 08:55:58 -07001027// /sys/device_dir/0/01/tty [empty directory]
Ben Chan4eb4ddf2013-06-20 22:16:56 -07001028TEST_F(DeviceInfoTechnologyTest, CDCEthernetModem2) {
Paul Stewartca876ee2012-04-21 08:55:58 -07001029 CreateInfoSymLink("device", "../../../device_dir/0/00");
1030 FilePath device_root(temp_dir_.path().Append("sys/device_dir/0"));
1031 FilePath device_path(device_root.Append("00"));
Ben Chan4eb4ddf2013-06-20 22:16:56 -07001032 FilePath driver_symlink(device_path.Append("driver"));
Paul Stewartca876ee2012-04-21 08:55:58 -07001033 EXPECT_TRUE(file_util::CreateDirectory(device_path));
1034 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
Ben Chan4eb4ddf2013-06-20 22:16:56 -07001035 driver_symlink));
Paul Stewartca876ee2012-04-21 08:55:58 -07001036 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/tty")));
1037 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
Ben Chan4eb4ddf2013-06-20 22:16:56 -07001038
1039 EXPECT_TRUE(file_util::Delete(driver_symlink, false));
1040 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ncm"),
1041 driver_symlink));
1042 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
Paul Stewartca876ee2012-04-21 08:55:58 -07001043}
1044
1045// Modem with relative driver path with lower-level tty file.
1046// /sys/class/net/dev0/device -> ../../../device_dir/0/00
Ben Chan4eb4ddf2013-06-20 22:16:56 -07001047// /sys/device_dir/0/00/driver -> /drivers/cdc_ether or /drivers/cdc_ncm
Paul Stewartca876ee2012-04-21 08:55:58 -07001048// /sys/device_dir/0/01/yyy/tty [empty directory]
Ben Chan4eb4ddf2013-06-20 22:16:56 -07001049TEST_F(DeviceInfoTechnologyTest, CDCEthernetModem3) {
Paul Stewartca876ee2012-04-21 08:55:58 -07001050 CreateInfoSymLink("device", "../../../device_dir/0/00");
1051 FilePath device_root(temp_dir_.path().Append("sys/device_dir/0"));
1052 FilePath device_path(device_root.Append("00"));
Ben Chan4eb4ddf2013-06-20 22:16:56 -07001053 FilePath driver_symlink(device_path.Append("driver"));
Paul Stewartca876ee2012-04-21 08:55:58 -07001054 EXPECT_TRUE(file_util::CreateDirectory(device_path));
1055 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ether"),
Ben Chan4eb4ddf2013-06-20 22:16:56 -07001056 driver_symlink));
Paul Stewartca876ee2012-04-21 08:55:58 -07001057 EXPECT_TRUE(file_util::CreateDirectory(device_root.Append("01/yyy/tty")));
1058 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
Ben Chan4eb4ddf2013-06-20 22:16:56 -07001059
1060 EXPECT_TRUE(file_util::Delete(driver_symlink, false));
1061 EXPECT_TRUE(file_util::CreateSymbolicLink(FilePath("/drivers/cdc_ncm"),
1062 driver_symlink));
1063 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
Paul Stewartca876ee2012-04-21 08:55:58 -07001064}
1065
1066TEST_F(DeviceInfoTechnologyTest, CDCEtherNonModem) {
1067 CreateInfoSymLink("device", "device_dir");
1068 CreateInfoSymLink("device_dir/driver", "cdc_ether");
Paul Stewart050cfc02012-07-06 20:38:54 -07001069 EXPECT_EQ(Technology::kCDCEthernet, GetDeviceTechnology());
Paul Stewartca876ee2012-04-21 08:55:58 -07001070}
1071
Ben Chan4eb4ddf2013-06-20 22:16:56 -07001072TEST_F(DeviceInfoTechnologyTest, CDCNcmNonModem) {
1073 CreateInfoSymLink("device", "device_dir");
1074 CreateInfoSymLink("device_dir/driver", "cdc_ncm");
1075 EXPECT_EQ(Technology::kCDCEthernet, GetDeviceTechnology());
1076}
1077
Jason Glasgowabc54032012-04-20 16:08:32 -04001078TEST_F(DeviceInfoTechnologyTest, PseudoModem) {
1079 SetDeviceName("pseudomodem");
1080 CreateInfoSymLink("device", "device_dir");
1081 CreateInfoSymLink("device_dir/driver", "cdc_ether");
1082 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
1083
1084 SetDeviceName("pseudomodem9");
1085 CreateInfoSymLink("device", "device_dir");
1086 CreateInfoSymLink("device_dir/driver", "cdc_ether");
1087 EXPECT_EQ(Technology::kCellular, GetDeviceTechnology());
1088}
1089
Paul Stewart050cfc02012-07-06 20:38:54 -07001090class DeviceInfoForDelayedCreationTest : public DeviceInfo {
1091 public:
1092 DeviceInfoForDelayedCreationTest(ControlInterface *control_interface,
1093 EventDispatcher *dispatcher,
1094 Metrics *metrics,
1095 Manager *manager)
1096 : DeviceInfo(control_interface, dispatcher, metrics, manager) {}
1097 MOCK_METHOD4(CreateDevice, DeviceRefPtr(const std::string &link_name,
1098 const std::string &address,
1099 int interface_index,
1100 Technology::Identifier technology));
1101 MOCK_METHOD1(GetDeviceTechnology,
1102 Technology::Identifier(const string &iface_name));
1103};
1104
1105class DeviceInfoDelayedCreationTest : public DeviceInfoTest {
1106 public:
1107 DeviceInfoDelayedCreationTest()
1108 : DeviceInfoTest(),
1109 test_device_info_(
1110 &control_interface_, &dispatcher_, &metrics_, &manager_) {}
1111 virtual ~DeviceInfoDelayedCreationTest() {}
1112
1113 virtual std::set<int> &GetDelayedDevices() {
1114 return test_device_info_.delayed_devices_;
1115 }
1116
1117 void DelayedDeviceCreationTask() {
1118 test_device_info_.DelayedDeviceCreationTask();
1119 }
1120
1121 void AddDelayedDevice() {
1122 scoped_ptr<RTNLMessage> message(BuildLinkMessage(RTNLMessage::kModeAdd));
1123 EXPECT_CALL(test_device_info_, GetDeviceTechnology(kTestDeviceName))
1124 .WillOnce(Return(Technology::kCDCEthernet));
1125 EXPECT_CALL(test_device_info_, CreateDevice(
1126 kTestDeviceName, _, kTestDeviceIndex, Technology::kCDCEthernet))
1127 .WillOnce(Return(DeviceRefPtr()));
1128 test_device_info_.AddLinkMsgHandler(*message);
1129 Mock::VerifyAndClearExpectations(&test_device_info_);
1130 // We need to insert the device index ourselves since we have mocked
1131 // out CreateDevice. This insertion is tested in CreateDeviceCDCEthernet
1132 // above.
1133 GetDelayedDevices().insert(kTestDeviceIndex);
1134 }
1135
Wade Guthrie7347bf22013-04-30 11:21:51 -07001136 void TriggerOnWiFiInterfaceInfoReceived(const Nl80211Message &message) {
Paul Stewart2ddf2c62013-04-16 09:47:34 -07001137 test_device_info_.OnWiFiInterfaceInfoReceived(message);
1138 }
1139
Paul Stewart050cfc02012-07-06 20:38:54 -07001140 protected:
1141 DeviceInfoForDelayedCreationTest test_device_info_;
1142};
1143
1144TEST_F(DeviceInfoDelayedCreationTest, NoDevices) {
1145 EXPECT_TRUE(GetDelayedDevices().empty());
1146 EXPECT_CALL(test_device_info_, GetDeviceTechnology(_)).Times(0);
1147 DelayedDeviceCreationTask();
1148}
1149
1150TEST_F(DeviceInfoDelayedCreationTest, EthernetDevice) {
1151 AddDelayedDevice();
1152 EXPECT_CALL(test_device_info_, GetDeviceTechnology(_))
1153 .WillOnce(Return(Technology::kCDCEthernet));
1154 EXPECT_CALL(test_device_info_, CreateDevice(
1155 kTestDeviceName, _, kTestDeviceIndex, Technology::kEthernet))
1156 .WillOnce(Return(DeviceRefPtr()));
1157 DelayedDeviceCreationTask();
1158 EXPECT_TRUE(GetDelayedDevices().empty());
1159}
1160
1161TEST_F(DeviceInfoDelayedCreationTest, CellularDevice) {
1162 AddDelayedDevice();
1163 EXPECT_CALL(test_device_info_, GetDeviceTechnology(_))
1164 .WillOnce(Return(Technology::kCellular));
1165 EXPECT_CALL(test_device_info_, CreateDevice(
1166 kTestDeviceName, _, kTestDeviceIndex, Technology::kCellular))
1167 .WillOnce(Return(DeviceRefPtr()));
1168 DelayedDeviceCreationTask();
1169 EXPECT_TRUE(GetDelayedDevices().empty());
1170}
1171
Paul Stewart2ddf2c62013-04-16 09:47:34 -07001172TEST_F(DeviceInfoDelayedCreationTest, WiFiDevice) {
1173 ScopedMockLog log;
Paul Stewart2ddf2c62013-04-16 09:47:34 -07001174 EXPECT_CALL(log, Log(logging::LOG_ERROR, _,
1175 HasSubstr("Message is not a new interface response")));
1176 GetInterfaceMessage non_interface_response_message;
1177 TriggerOnWiFiInterfaceInfoReceived(non_interface_response_message);
1178 Mock::VerifyAndClearExpectations(&log);
1179
1180 EXPECT_CALL(log, Log(logging::LOG_ERROR, _,
1181 HasSubstr("Message contains no interface index")));
1182 NewInterfaceMessage message;
1183 TriggerOnWiFiInterfaceInfoReceived(message);
1184 Mock::VerifyAndClearExpectations(&log);
1185
1186 message.attributes()->CreateAttribute(
1187 NL80211_ATTR_IFINDEX, base::Bind(
1188 &NetlinkAttribute::NewNl80211AttributeFromId));
1189 message.attributes()->SetU32AttributeValue(NL80211_ATTR_IFINDEX,
1190 kTestDeviceIndex);
1191 EXPECT_CALL(log, Log(logging::LOG_ERROR, _,
1192 HasSubstr("Message contains no interface type")));
1193 TriggerOnWiFiInterfaceInfoReceived(message);
1194 Mock::VerifyAndClearExpectations(&log);
1195
1196 message.attributes()->CreateAttribute(
1197 NL80211_ATTR_IFTYPE, base::Bind(
1198 &NetlinkAttribute::NewNl80211AttributeFromId));
1199 message.attributes()->SetU32AttributeValue(NL80211_ATTR_IFTYPE,
1200 NL80211_IFTYPE_AP);
1201 EXPECT_CALL(log, Log(logging::LOG_ERROR, _,
1202 HasSubstr("Could not find device info for interface")));
1203 TriggerOnWiFiInterfaceInfoReceived(message);
1204 Mock::VerifyAndClearExpectations(&log);
1205
1206 // Use the AddDelayedDevice() method to create a device info entry with no
1207 // associated device.
1208 AddDelayedDevice();
1209
1210 EXPECT_CALL(log, Log(logging::LOG_INFO, _,
1211 HasSubstr("it is not in station mode")));
1212 TriggerOnWiFiInterfaceInfoReceived(message);
1213 Mock::VerifyAndClearExpectations(&log);
1214 Mock::VerifyAndClearExpectations(&manager_);
1215
1216 message.attributes()->SetU32AttributeValue(NL80211_ATTR_IFTYPE,
1217 NL80211_IFTYPE_STATION);
1218 EXPECT_CALL(manager_, RegisterDevice(_));
1219 EXPECT_CALL(manager_, device_info())
1220 .WillRepeatedly(Return(&test_device_info_));
1221 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
1222 EXPECT_CALL(log, Log(logging::LOG_INFO, _,
1223 HasSubstr("Creating WiFi device")));
1224 TriggerOnWiFiInterfaceInfoReceived(message);
1225 Mock::VerifyAndClearExpectations(&log);
1226 Mock::VerifyAndClearExpectations(&manager_);
1227
1228 EXPECT_CALL(manager_, RegisterDevice(_)).Times(0);
1229 EXPECT_CALL(log, Log(logging::LOG_ERROR, _,
1230 HasSubstr("Device already created for interface")));
1231 TriggerOnWiFiInterfaceInfoReceived(message);
1232}
1233
Chris Masone9be4a9d2011-05-16 15:44:09 -07001234} // namespace shill