blob: eb26d3a6ca59cf3c2dd16e9342248c98267d7af4 [file] [log] [blame]
Thieu Le3426c8f2012-01-11 17:35:11 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Darin Petkovafa6fc42011-06-21 16:21:08 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Darin Petkovafa6fc42011-06-21 16:21:08 -07005#include "shill/device.h"
Darin Petkovafa6fc42011-06-21 16:21:08 -07006
Chris Masone34af2182011-08-22 11:59:36 -07007#include <ctype.h>
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -07008#include <sys/socket.h>
9#include <linux/if.h> // Needs typedefs from sys/socket.h.
Chris Masone34af2182011-08-22 11:59:36 -070010
Chris Masone3bd3c8c2011-06-13 08:20:26 -070011#include <map>
12#include <string>
13#include <vector>
14
Chris Masone3bd3c8c2011-06-13 08:20:26 -070015#include <chromeos/dbus/service_constants.h>
Chris Masone34af2182011-08-22 11:59:36 -070016#include <dbus-c++/dbus.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070017#include <gmock/gmock.h>
Chris Masone34af2182011-08-22 11:59:36 -070018#include <gtest/gtest.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070019
20#include "shill/dbus_adaptor.h"
21#include "shill/dhcp_provider.h"
Paul Stewart26b327e2011-10-19 11:38:09 -070022#include "shill/event_dispatcher.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070023#include "shill/manager.h"
Chris Masone95207da2011-06-29 16:50:49 -070024#include "shill/mock_adaptors.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070025#include "shill/mock_control.h"
26#include "shill/mock_device.h"
27#include "shill/mock_glib.h"
Chris Masone34af2182011-08-22 11:59:36 -070028#include "shill/mock_ipconfig.h"
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -070029#include "shill/mock_rtnl_handler.h"
Paul Stewart03dba0b2011-08-22 16:32:45 -070030#include "shill/mock_service.h"
Chris Masone5dec5f42011-07-22 14:07:55 -070031#include "shill/mock_store.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070032#include "shill/property_store_unittest.h"
Gaurav Shah435de2c2011-11-17 19:01:07 -080033#include "shill/technology.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070034
35using std::map;
36using std::string;
37using std::vector;
38using ::testing::_;
Chris Masone5dec5f42011-07-22 14:07:55 -070039using ::testing::AtLeast;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070040using ::testing::NiceMock;
41using ::testing::Return;
Paul Stewart03dba0b2011-08-22 16:32:45 -070042using ::testing::StrictMock;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070043using ::testing::Test;
Chris Masone34af2182011-08-22 11:59:36 -070044using ::testing::Values;
Darin Petkovafa6fc42011-06-21 16:21:08 -070045
46namespace shill {
47
Chris Masone3bd3c8c2011-06-13 08:20:26 -070048class DeviceTest : public PropertyStoreTest {
Darin Petkovafa6fc42011-06-21 16:21:08 -070049 public:
50 DeviceTest()
Chris Masone2176a882011-09-14 22:29:15 -070051 : device_(new Device(control_interface(),
Chris Masone626719f2011-08-18 16:58:48 -070052 NULL,
53 NULL,
Thieu Le3426c8f2012-01-11 17:35:11 -080054 NULL,
Chris Masone626719f2011-08-18 16:58:48 -070055 kDeviceName,
56 kDeviceAddress,
Gaurav Shah435de2c2011-11-17 19:01:07 -080057 0,
58 Technology::kUnknown)) {
Chris Masone2176a882011-09-14 22:29:15 -070059 DHCPProvider::GetInstance()->glib_ = glib();
60 DHCPProvider::GetInstance()->control_interface_ = control_interface();
Darin Petkovafa6fc42011-06-21 16:21:08 -070061 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -070062 virtual ~DeviceTest() {}
Darin Petkovafa6fc42011-06-21 16:21:08 -070063
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -070064 virtual void SetUp() {
65 device_->rtnl_handler_ = &rtnl_handler_;
66 }
67
Darin Petkovafa6fc42011-06-21 16:21:08 -070068 protected:
Chris Masone626719f2011-08-18 16:58:48 -070069 static const char kDeviceName[];
70 static const char kDeviceAddress[];
71
Darin Petkovafa6fc42011-06-21 16:21:08 -070072 MockControl control_interface_;
73 DeviceRefPtr device_;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -070074 StrictMock<MockRTNLHandler> rtnl_handler_;
Darin Petkovafa6fc42011-06-21 16:21:08 -070075};
76
Chris Masone626719f2011-08-18 16:58:48 -070077const char DeviceTest::kDeviceName[] = "testdevice";
78const char DeviceTest::kDeviceAddress[] = "address";
79
Chris Masone3bd3c8c2011-06-13 08:20:26 -070080TEST_F(DeviceTest, Contains) {
mukesh agrawalde29fa82011-09-16 16:16:36 -070081 EXPECT_TRUE(device_->store().Contains(flimflam::kNameProperty));
82 EXPECT_FALSE(device_->store().Contains(""));
Chris Masone3bd3c8c2011-06-13 08:20:26 -070083}
84
Chris Masonea8a2c252011-06-27 22:16:30 -070085TEST_F(DeviceTest, GetProperties) {
86 map<string, ::DBus::Variant> props;
87 Error error(Error::kInvalidProperty, "");
88 {
89 ::DBus::Error dbus_error;
90 bool expected = true;
mukesh agrawalde29fa82011-09-16 16:16:36 -070091 device_->mutable_store()->SetBoolProperty(flimflam::kPoweredProperty,
92 expected,
93 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -070094 DBusAdaptor::GetProperties(device_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -070095 ASSERT_FALSE(props.find(flimflam::kPoweredProperty) == props.end());
96 EXPECT_EQ(props[flimflam::kPoweredProperty].reader().get_bool(),
97 expected);
98 }
99 {
100 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -0700101 DBusAdaptor::GetProperties(device_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700102 ASSERT_FALSE(props.find(flimflam::kNameProperty) == props.end());
103 EXPECT_EQ(props[flimflam::kNameProperty].reader().get_string(),
104 string(kDeviceName));
105 }
106}
107
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800108TEST_F(DeviceTest, SetProperty) {
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700109 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800110 EXPECT_TRUE(DBusAdaptor::SetProperty(device_->mutable_store(),
111 flimflam::kPoweredProperty,
112 PropertyStoreTest::kBoolV,
113 &error));
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700114
Chris Masoneb925cc82011-06-22 15:39:57 -0700115 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800116 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
117 flimflam::kAddressProperty,
118 PropertyStoreTest::kStringV,
119 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700120 EXPECT_EQ(invalid_args(), error.name());
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700121}
122
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800123TEST_F(DeviceTest, ClearProperty) {
124 ::DBus::Error error;
125 EXPECT_TRUE(device_->powered());
126
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800127 EXPECT_TRUE(DBusAdaptor::SetProperty(device_->mutable_store(),
128 flimflam::kPoweredProperty,
129 PropertyStoreTest::kBoolV,
130 &error));
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800131 EXPECT_FALSE(device_->powered());
132
133 EXPECT_TRUE(DBusAdaptor::ClearProperty(device_->mutable_store(),
134 flimflam::kPoweredProperty,
135 &error));
136 EXPECT_TRUE(device_->powered());
137}
138
139TEST_F(DeviceTest, ClearReadOnlyProperty) {
140 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800141 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
142 flimflam::kAddressProperty,
143 PropertyStoreTest::kStringV,
144 &error));
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800145}
146
147TEST_F(DeviceTest, ClearReadOnlyDerivedProperty) {
148 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800149 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
150 flimflam::kIPConfigsProperty,
151 PropertyStoreTest::kStringsV,
152 &error));
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800153}
154
Darin Petkovafa6fc42011-06-21 16:21:08 -0700155TEST_F(DeviceTest, TechnologyIs) {
Paul Stewartfdd16072011-09-16 12:41:35 -0700156 EXPECT_FALSE(device_->TechnologyIs(Technology::kEthernet));
Darin Petkovafa6fc42011-06-21 16:21:08 -0700157}
158
159TEST_F(DeviceTest, DestroyIPConfig) {
160 ASSERT_FALSE(device_->ipconfig_.get());
Chris Masone2176a882011-09-14 22:29:15 -0700161 device_->ipconfig_ = new IPConfig(control_interface(), kDeviceName);
Darin Petkovafa6fc42011-06-21 16:21:08 -0700162 device_->DestroyIPConfig();
163 ASSERT_FALSE(device_->ipconfig_.get());
164}
165
166TEST_F(DeviceTest, DestroyIPConfigNULL) {
167 ASSERT_FALSE(device_->ipconfig_.get());
168 device_->DestroyIPConfig();
169 ASSERT_FALSE(device_->ipconfig_.get());
170}
171
Paul Stewart2bf1d352011-12-06 15:02:55 -0800172TEST_F(DeviceTest, AcquireIPConfig) {
Chris Masone2176a882011-09-14 22:29:15 -0700173 device_->ipconfig_ = new IPConfig(control_interface(), "randomname");
Paul Stewartd32f4842012-01-11 16:08:13 -0800174 device_->manager_ = manager();
Chris Masone2176a882011-09-14 22:29:15 -0700175 EXPECT_CALL(*glib(), SpawnAsync(_, _, _, _, _, _, _, _))
Darin Petkovafa6fc42011-06-21 16:21:08 -0700176 .WillOnce(Return(false));
Paul Stewart2bf1d352011-12-06 15:02:55 -0800177 EXPECT_FALSE(device_->AcquireIPConfig());
Darin Petkovafa6fc42011-06-21 16:21:08 -0700178 ASSERT_TRUE(device_->ipconfig_.get());
179 EXPECT_EQ(kDeviceName, device_->ipconfig_->device_name());
180 EXPECT_TRUE(device_->ipconfig_->update_callback_.get());
181}
182
Chris Masone5dec5f42011-07-22 14:07:55 -0700183TEST_F(DeviceTest, Load) {
184 NiceMock<MockStore> storage;
185 const string id = device_->GetStorageIdentifier();
186 EXPECT_CALL(storage, ContainsGroup(id)).WillOnce(Return(true));
187 EXPECT_CALL(storage, GetBool(id, _, _))
188 .Times(AtLeast(1))
189 .WillRepeatedly(Return(true));
190 EXPECT_TRUE(device_->Load(&storage));
191}
192
193TEST_F(DeviceTest, Save) {
194 NiceMock<MockStore> storage;
195 const string id = device_->GetStorageIdentifier();
Chris Masone5dec5f42011-07-22 14:07:55 -0700196 EXPECT_CALL(storage, SetString(id, _, _))
197 .Times(AtLeast(1))
198 .WillRepeatedly(Return(true));
199 EXPECT_CALL(storage, SetBool(id, _, _))
200 .Times(AtLeast(1))
201 .WillRepeatedly(Return(true));
Chris Masone2176a882011-09-14 22:29:15 -0700202 scoped_refptr<MockIPConfig> ipconfig = new MockIPConfig(control_interface(),
Chris Masone34af2182011-08-22 11:59:36 -0700203 kDeviceName);
204 EXPECT_CALL(*ipconfig.get(), Save(_, _))
205 .WillOnce(Return(true));
206 device_->ipconfig_ = ipconfig;
Chris Masone5dec5f42011-07-22 14:07:55 -0700207 EXPECT_TRUE(device_->Save(&storage));
208}
209
Chris Masone34af2182011-08-22 11:59:36 -0700210TEST_F(DeviceTest, StorageIdGeneration) {
211 string to_process("/device/stuff/0");
212 ControlInterface::RpcIdToStorageId(&to_process);
213 EXPECT_TRUE(isalpha(to_process[0]));
214 EXPECT_EQ(string::npos, to_process.find('/'));
215}
216
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800217MATCHER(IsNullRefPtr, "") {
218 return !arg;
219}
220
221MATCHER(NotNullRefPtr, "") {
222 return arg;
223}
224
Paul Stewart03dba0b2011-08-22 16:32:45 -0700225TEST_F(DeviceTest, SelectedService) {
226 EXPECT_FALSE(device_->selected_service_.get());
227 device_->SetServiceState(Service::kStateAssociating);
228 scoped_refptr<MockService> service(
Chris Masone2176a882011-09-14 22:29:15 -0700229 new StrictMock<MockService>(control_interface(),
230 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800231 metrics(),
Chris Masone9d779932011-08-25 16:33:41 -0700232 manager()));
Paul Stewart03dba0b2011-08-22 16:32:45 -0700233 device_->SelectService(service);
234 EXPECT_TRUE(device_->selected_service_.get() == service.get());
235
236 EXPECT_CALL(*service.get(), SetState(Service::kStateConfiguring));
237 device_->SetServiceState(Service::kStateConfiguring);
238 EXPECT_CALL(*service.get(), SetFailure(Service::kFailureOutOfRange));
239 device_->SetServiceFailure(Service::kFailureOutOfRange);
240
241 // Service should be returned to "Idle" state
242 EXPECT_CALL(*service.get(), state())
243 .WillOnce(Return(Service::kStateUnknown));
244 EXPECT_CALL(*service.get(), SetState(Service::kStateIdle));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800245 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Paul Stewart03dba0b2011-08-22 16:32:45 -0700246 device_->SelectService(NULL);
247
248 // A service in the "Failure" state should not be reset to "Idle"
249 device_->SelectService(service);
250 EXPECT_CALL(*service.get(), state())
251 .WillOnce(Return(Service::kStateFailure));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800252 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Paul Stewart03dba0b2011-08-22 16:32:45 -0700253 device_->SelectService(NULL);
254}
255
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800256TEST_F(DeviceTest, IPConfigUpdatedFailure) {
257 scoped_refptr<MockService> service(
258 new StrictMock<MockService>(control_interface(),
259 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800260 metrics(),
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800261 manager()));
262 device_->SelectService(service);
263 EXPECT_CALL(*service.get(), SetState(Service::kStateDisconnected));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800264 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800265 device_->IPConfigUpdatedCallback(NULL, false);
266}
267
268TEST_F(DeviceTest, IPConfigUpdatedSuccess) {
269 scoped_refptr<MockService> service(
270 new StrictMock<MockService>(control_interface(),
271 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800272 metrics(),
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800273 manager()));
274 device_->SelectService(service);
275 device_->manager_ = manager();
276 scoped_refptr<MockIPConfig> ipconfig = new MockIPConfig(control_interface(),
277 kDeviceName);
278 EXPECT_CALL(*service.get(), SetState(Service::kStateConnected));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800279 EXPECT_CALL(*service.get(), SetConnection(NotNullRefPtr()));
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800280 device_->IPConfigUpdatedCallback(ipconfig.get(), true);
281}
282
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700283TEST_F(DeviceTest, Stop) {
284 device_->ipconfig_ = new IPConfig(&control_interface_, kDeviceName);
285 scoped_refptr<MockService> service(
286 new NiceMock<MockService>(&control_interface_,
287 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800288 metrics(),
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700289 manager()));
290 device_->SelectService(service);
291
292 EXPECT_CALL(*service.get(), state()).
293 WillRepeatedly(Return(Service::kStateConnected));
294 EXPECT_CALL(*dynamic_cast<DeviceMockAdaptor *>(device_->adaptor_.get()),
295 UpdateEnabled());
296 EXPECT_CALL(rtnl_handler_, SetInterfaceFlags(_, 0, IFF_UP));
297 device_->Stop();
298
299 EXPECT_FALSE(device_->ipconfig_.get());
300 EXPECT_FALSE(device_->selected_service_.get());
301}
302
Darin Petkovafa6fc42011-06-21 16:21:08 -0700303} // namespace shill