blob: cb769ad7a26b59e6e31b5628b7e148b3d57fb208 [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 Masone95207da2011-06-29 16:50:49 -070023#include "shill/mock_adaptors.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070024#include "shill/mock_control.h"
Paul Stewart20088d82012-02-16 06:58:55 -080025#include "shill/mock_connection.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070026#include "shill/mock_device.h"
Paul Stewart20088d82012-02-16 06:58:55 -080027#include "shill/mock_device_info.h"
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -070028#include "shill/mock_dhcp_config.h"
29#include "shill/mock_dhcp_provider.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070030#include "shill/mock_glib.h"
Chris Masone34af2182011-08-22 11:59:36 -070031#include "shill/mock_ipconfig.h"
Paul Stewart20088d82012-02-16 06:58:55 -080032#include "shill/mock_manager.h"
Thieu Le85e050b2012-03-13 15:04:38 -070033#include "shill/mock_metrics.h"
Paul Stewartc681fa02012-03-02 19:40:04 -080034#include "shill/mock_portal_detector.h"
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -070035#include "shill/mock_rtnl_handler.h"
Paul Stewart03dba0b2011-08-22 16:32:45 -070036#include "shill/mock_service.h"
Chris Masone5dec5f42011-07-22 14:07:55 -070037#include "shill/mock_store.h"
Paul Stewart20088d82012-02-16 06:58:55 -080038#include "shill/portal_detector.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070039#include "shill/property_store_unittest.h"
mukesh agrawalcc0fded2012-05-09 13:40:58 -070040#include "shill/static_ip_parameters.h"
Gaurav Shah435de2c2011-11-17 19:01:07 -080041#include "shill/technology.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070042
43using std::map;
44using std::string;
45using std::vector;
46using ::testing::_;
mukesh agrawalcc0fded2012-05-09 13:40:58 -070047using ::testing::AnyNumber;
Chris Masone5dec5f42011-07-22 14:07:55 -070048using ::testing::AtLeast;
Thieu Le85e050b2012-03-13 15:04:38 -070049using ::testing::Mock;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070050using ::testing::NiceMock;
51using ::testing::Return;
Paul Stewart20088d82012-02-16 06:58:55 -080052using ::testing::ReturnRef;
Paul Stewart03dba0b2011-08-22 16:32:45 -070053using ::testing::StrictMock;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070054using ::testing::Test;
Chris Masone34af2182011-08-22 11:59:36 -070055using ::testing::Values;
Darin Petkovafa6fc42011-06-21 16:21:08 -070056
57namespace shill {
58
Eric Shienbrood9a245532012-03-07 14:20:39 -050059class TestDevice : public Device {
60 public:
61 TestDevice(ControlInterface *control_interface,
62 EventDispatcher *dispatcher,
63 Metrics *metrics,
64 Manager *manager,
65 const std::string &link_name,
66 const std::string &address,
67 int interface_index,
68 Technology::Identifier technology)
69 : Device(control_interface, dispatcher, metrics, manager, link_name,
70 address, interface_index, technology) {}
71 ~TestDevice() {}
72 virtual void Start(Error *error,
Jason Glasgow4a490792012-04-10 15:02:05 -040073 const EnabledStateChangedCallback &callback) {
74 DCHECK(error);
75 }
Eric Shienbrood9a245532012-03-07 14:20:39 -050076 virtual void Stop(Error *error,
Jason Glasgow4a490792012-04-10 15:02:05 -040077 const EnabledStateChangedCallback &callback) {
78 DCHECK(error);
79 }
Eric Shienbrood9a245532012-03-07 14:20:39 -050080};
81
Chris Masone3bd3c8c2011-06-13 08:20:26 -070082class DeviceTest : public PropertyStoreTest {
Darin Petkovafa6fc42011-06-21 16:21:08 -070083 public:
84 DeviceTest()
Eric Shienbrood9a245532012-03-07 14:20:39 -050085 : device_(new TestDevice(control_interface(),
86 dispatcher(),
87 NULL,
88 manager(),
89 kDeviceName,
90 kDeviceAddress,
91 kDeviceInterfaceIndex,
92 Technology::kUnknown)),
Paul Stewartc681fa02012-03-02 19:40:04 -080093 device_info_(control_interface(), NULL, NULL, NULL) {
Chris Masone2176a882011-09-14 22:29:15 -070094 DHCPProvider::GetInstance()->glib_ = glib();
95 DHCPProvider::GetInstance()->control_interface_ = control_interface();
mukesh agrawalcc0fded2012-05-09 13:40:58 -070096 DHCPProvider::GetInstance()->dispatcher_ = dispatcher();
Darin Petkovafa6fc42011-06-21 16:21:08 -070097 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -070098 virtual ~DeviceTest() {}
Darin Petkovafa6fc42011-06-21 16:21:08 -070099
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700100 virtual void SetUp() {
Thieu Le85e050b2012-03-13 15:04:38 -0700101 device_->metrics_ = &metrics_;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700102 device_->rtnl_handler_ = &rtnl_handler_;
103 }
104
Darin Petkovafa6fc42011-06-21 16:21:08 -0700105 protected:
Chris Masone626719f2011-08-18 16:58:48 -0700106 static const char kDeviceName[];
107 static const char kDeviceAddress[];
Thieu Lefb46caf2012-03-08 11:57:15 -0800108 static const int kDeviceInterfaceIndex;
Chris Masone626719f2011-08-18 16:58:48 -0700109
Darin Petkov79d74c92012-03-07 17:20:32 +0100110 void OnIPConfigUpdated(const IPConfigRefPtr &ipconfig, bool success) {
111 device_->OnIPConfigUpdated(ipconfig, success);
Paul Stewart20088d82012-02-16 06:58:55 -0800112 }
113
114 void SelectService(const ServiceRefPtr service) {
115 device_->SelectService(service);
116 }
117
Paul Stewart20088d82012-02-16 06:58:55 -0800118 void SetConnection(ConnectionRefPtr connection) {
119 device_->connection_ = connection;
120 }
121
Darin Petkovafa6fc42011-06-21 16:21:08 -0700122 MockControl control_interface_;
123 DeviceRefPtr device_;
Paul Stewartc681fa02012-03-02 19:40:04 -0800124 MockDeviceInfo device_info_;
Thieu Le85e050b2012-03-13 15:04:38 -0700125 MockMetrics metrics_;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700126 StrictMock<MockRTNLHandler> rtnl_handler_;
Darin Petkovafa6fc42011-06-21 16:21:08 -0700127};
128
Chris Masone626719f2011-08-18 16:58:48 -0700129const char DeviceTest::kDeviceName[] = "testdevice";
130const char DeviceTest::kDeviceAddress[] = "address";
Thieu Lefb46caf2012-03-08 11:57:15 -0800131const int DeviceTest::kDeviceInterfaceIndex = 0;
Chris Masone626719f2011-08-18 16:58:48 -0700132
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700133TEST_F(DeviceTest, Contains) {
mukesh agrawalde29fa82011-09-16 16:16:36 -0700134 EXPECT_TRUE(device_->store().Contains(flimflam::kNameProperty));
135 EXPECT_FALSE(device_->store().Contains(""));
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700136}
137
Chris Masonea8a2c252011-06-27 22:16:30 -0700138TEST_F(DeviceTest, GetProperties) {
139 map<string, ::DBus::Variant> props;
140 Error error(Error::kInvalidProperty, "");
Eric Shienbrood9a245532012-03-07 14:20:39 -0500141 ::DBus::Error dbus_error;
142 DBusAdaptor::GetProperties(device_->store(), &props, &dbus_error);
143 ASSERT_FALSE(props.find(flimflam::kNameProperty) == props.end());
144 EXPECT_EQ(props[flimflam::kNameProperty].reader().get_string(),
145 string(kDeviceName));
Chris Masonea8a2c252011-06-27 22:16:30 -0700146}
147
Eric Shienbrood9a245532012-03-07 14:20:39 -0500148// Note: there are currently no writeable Device properties that
149// aren't registered in a subclass.
150TEST_F(DeviceTest, SetReadOnlyProperty) {
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700151 ::DBus::Error error;
Chris Masoneb925cc82011-06-22 15:39:57 -0700152 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800153 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
154 flimflam::kAddressProperty,
155 PropertyStoreTest::kStringV,
156 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700157 EXPECT_EQ(invalid_args(), error.name());
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700158}
159
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800160TEST_F(DeviceTest, ClearReadOnlyProperty) {
161 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800162 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
163 flimflam::kAddressProperty,
164 PropertyStoreTest::kStringV,
165 &error));
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800166}
167
168TEST_F(DeviceTest, ClearReadOnlyDerivedProperty) {
169 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800170 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
171 flimflam::kIPConfigsProperty,
172 PropertyStoreTest::kStringsV,
173 &error));
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800174}
175
Darin Petkovafa6fc42011-06-21 16:21:08 -0700176TEST_F(DeviceTest, TechnologyIs) {
Paul Stewartfdd16072011-09-16 12:41:35 -0700177 EXPECT_FALSE(device_->TechnologyIs(Technology::kEthernet));
Darin Petkovafa6fc42011-06-21 16:21:08 -0700178}
179
180TEST_F(DeviceTest, DestroyIPConfig) {
181 ASSERT_FALSE(device_->ipconfig_.get());
Chris Masone2176a882011-09-14 22:29:15 -0700182 device_->ipconfig_ = new IPConfig(control_interface(), kDeviceName);
Darin Petkovafa6fc42011-06-21 16:21:08 -0700183 device_->DestroyIPConfig();
184 ASSERT_FALSE(device_->ipconfig_.get());
185}
186
187TEST_F(DeviceTest, DestroyIPConfigNULL) {
188 ASSERT_FALSE(device_->ipconfig_.get());
189 device_->DestroyIPConfig();
190 ASSERT_FALSE(device_->ipconfig_.get());
191}
192
Paul Stewart2bf1d352011-12-06 15:02:55 -0800193TEST_F(DeviceTest, AcquireIPConfig) {
Chris Masone2176a882011-09-14 22:29:15 -0700194 device_->ipconfig_ = new IPConfig(control_interface(), "randomname");
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -0700195 scoped_ptr<MockDHCPProvider> dhcp_provider(new MockDHCPProvider());
196 device_->dhcp_provider_ = dhcp_provider.get();
197 scoped_refptr<MockDHCPConfig> dhcp_config(new MockDHCPConfig(
198 control_interface(),
199 kDeviceName));
200 EXPECT_CALL(*dhcp_provider, CreateConfig(_, _, _, _))
201 .WillOnce(Return(dhcp_config));
202 EXPECT_CALL(*dhcp_config, RequestIP())
Darin Petkovafa6fc42011-06-21 16:21:08 -0700203 .WillOnce(Return(false));
Paul Stewart2bf1d352011-12-06 15:02:55 -0800204 EXPECT_FALSE(device_->AcquireIPConfig());
Darin Petkovafa6fc42011-06-21 16:21:08 -0700205 ASSERT_TRUE(device_->ipconfig_.get());
206 EXPECT_EQ(kDeviceName, device_->ipconfig_->device_name());
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500207 EXPECT_FALSE(device_->ipconfig_->update_callback_.is_null());
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -0700208 device_->dhcp_provider_ = NULL;
Darin Petkovafa6fc42011-06-21 16:21:08 -0700209}
210
Chris Masone5dec5f42011-07-22 14:07:55 -0700211TEST_F(DeviceTest, Load) {
212 NiceMock<MockStore> storage;
213 const string id = device_->GetStorageIdentifier();
214 EXPECT_CALL(storage, ContainsGroup(id)).WillOnce(Return(true));
215 EXPECT_CALL(storage, GetBool(id, _, _))
216 .Times(AtLeast(1))
217 .WillRepeatedly(Return(true));
218 EXPECT_TRUE(device_->Load(&storage));
219}
220
221TEST_F(DeviceTest, Save) {
222 NiceMock<MockStore> storage;
223 const string id = device_->GetStorageIdentifier();
Chris Masone5dec5f42011-07-22 14:07:55 -0700224 EXPECT_CALL(storage, SetString(id, _, _))
225 .Times(AtLeast(1))
226 .WillRepeatedly(Return(true));
227 EXPECT_CALL(storage, SetBool(id, _, _))
228 .Times(AtLeast(1))
229 .WillRepeatedly(Return(true));
Chris Masone2176a882011-09-14 22:29:15 -0700230 scoped_refptr<MockIPConfig> ipconfig = new MockIPConfig(control_interface(),
Chris Masone34af2182011-08-22 11:59:36 -0700231 kDeviceName);
232 EXPECT_CALL(*ipconfig.get(), Save(_, _))
233 .WillOnce(Return(true));
234 device_->ipconfig_ = ipconfig;
Chris Masone5dec5f42011-07-22 14:07:55 -0700235 EXPECT_TRUE(device_->Save(&storage));
236}
237
Chris Masone34af2182011-08-22 11:59:36 -0700238TEST_F(DeviceTest, StorageIdGeneration) {
239 string to_process("/device/stuff/0");
240 ControlInterface::RpcIdToStorageId(&to_process);
241 EXPECT_TRUE(isalpha(to_process[0]));
242 EXPECT_EQ(string::npos, to_process.find('/'));
243}
244
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800245MATCHER(IsNullRefPtr, "") {
246 return !arg;
247}
248
249MATCHER(NotNullRefPtr, "") {
250 return arg;
251}
252
Paul Stewart03dba0b2011-08-22 16:32:45 -0700253TEST_F(DeviceTest, SelectedService) {
254 EXPECT_FALSE(device_->selected_service_.get());
255 device_->SetServiceState(Service::kStateAssociating);
256 scoped_refptr<MockService> service(
Chris Masone2176a882011-09-14 22:29:15 -0700257 new StrictMock<MockService>(control_interface(),
258 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800259 metrics(),
Chris Masone9d779932011-08-25 16:33:41 -0700260 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800261 SelectService(service);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700262 EXPECT_TRUE(device_->selected_service_.get() == service.get());
263
264 EXPECT_CALL(*service.get(), SetState(Service::kStateConfiguring));
265 device_->SetServiceState(Service::kStateConfiguring);
266 EXPECT_CALL(*service.get(), SetFailure(Service::kFailureOutOfRange));
267 device_->SetServiceFailure(Service::kFailureOutOfRange);
268
269 // Service should be returned to "Idle" state
270 EXPECT_CALL(*service.get(), state())
271 .WillOnce(Return(Service::kStateUnknown));
272 EXPECT_CALL(*service.get(), SetState(Service::kStateIdle));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800273 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Paul Stewart20088d82012-02-16 06:58:55 -0800274 SelectService(NULL);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700275
276 // A service in the "Failure" state should not be reset to "Idle"
Paul Stewart20088d82012-02-16 06:58:55 -0800277 SelectService(service);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700278 EXPECT_CALL(*service.get(), state())
279 .WillOnce(Return(Service::kStateFailure));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800280 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Paul Stewart20088d82012-02-16 06:58:55 -0800281 SelectService(NULL);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700282}
283
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800284TEST_F(DeviceTest, IPConfigUpdatedFailure) {
285 scoped_refptr<MockService> service(
286 new StrictMock<MockService>(control_interface(),
287 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800288 metrics(),
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800289 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800290 SelectService(service);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800291 EXPECT_CALL(*service.get(), SetState(Service::kStateDisconnected));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800292 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Darin Petkov79d74c92012-03-07 17:20:32 +0100293 OnIPConfigUpdated(NULL, false);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800294}
295
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700296TEST_F(DeviceTest, IPConfigUpdatedFailureWithStatic) {
297 scoped_refptr<MockService> service(
298 new StrictMock<MockService>(control_interface(),
299 dispatcher(),
300 metrics(),
301 manager()));
302 SelectService(service);
303 service->static_ip_parameters_.args_.SetString(
304 flimflam::kAddressProperty, "1.1.1.1");
305 service->static_ip_parameters_.args_.SetInt(flimflam::kPrefixlenProperty, 16);
306 EXPECT_CALL(*service.get(), SetState(_)).Times(0);
307 EXPECT_CALL(*service.get(), SetConnection(_)).Times(0);
308 OnIPConfigUpdated(NULL, false);
309}
310
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800311TEST_F(DeviceTest, IPConfigUpdatedSuccess) {
312 scoped_refptr<MockService> service(
313 new StrictMock<MockService>(control_interface(),
314 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800315 metrics(),
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800316 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800317 SelectService(service);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800318 scoped_refptr<MockIPConfig> ipconfig = new MockIPConfig(control_interface(),
319 kDeviceName);
320 EXPECT_CALL(*service.get(), SetState(Service::kStateConnected));
Paul Stewart20088d82012-02-16 06:58:55 -0800321 EXPECT_CALL(*service.get(), IsConnected())
322 .WillRepeatedly(Return(true));
Paul Stewartd215af62012-04-24 23:25:50 -0700323 EXPECT_CALL(*service.get(), IsPortalDetectionDisabled())
324 .WillRepeatedly(Return(true));
Paul Stewart20088d82012-02-16 06:58:55 -0800325 EXPECT_CALL(*service.get(), SetState(Service::kStateOnline));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800326 EXPECT_CALL(*service.get(), SetConnection(NotNullRefPtr()));
Darin Petkov79d74c92012-03-07 17:20:32 +0100327 OnIPConfigUpdated(ipconfig.get(), true);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800328}
329
Thieu Lefb46caf2012-03-08 11:57:15 -0800330TEST_F(DeviceTest, Start) {
Paul Stewart8c116a92012-05-02 18:30:03 -0700331 EXPECT_FALSE(device_->running_);
332 EXPECT_FALSE(device_->enabled_);
333 EXPECT_FALSE(device_->enabled_pending_);
Eric Shienbrood9a245532012-03-07 14:20:39 -0500334 device_->SetEnabled(true);
Paul Stewart8c116a92012-05-02 18:30:03 -0700335 EXPECT_TRUE(device_->running_);
336 EXPECT_TRUE(device_->enabled_pending_);
Gary Morainbaeefdf2012-04-30 14:53:35 -0700337 device_->OnEnabledStateChanged(ResultCallback(),
338 Error(Error::kOperationFailed));
339 EXPECT_FALSE(device_->enabled_pending_);
Thieu Lefb46caf2012-03-08 11:57:15 -0800340}
341
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700342TEST_F(DeviceTest, Stop) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500343 device_->enabled_ = true;
344 device_->enabled_pending_ = true;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700345 device_->ipconfig_ = new IPConfig(&control_interface_, kDeviceName);
346 scoped_refptr<MockService> service(
347 new NiceMock<MockService>(&control_interface_,
348 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800349 metrics(),
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700350 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800351 SelectService(service);
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700352
353 EXPECT_CALL(*service.get(), state()).
354 WillRepeatedly(Return(Service::kStateConnected));
355 EXPECT_CALL(*dynamic_cast<DeviceMockAdaptor *>(device_->adaptor_.get()),
356 UpdateEnabled());
Eric Shienbrood9a245532012-03-07 14:20:39 -0500357 EXPECT_CALL(*dynamic_cast<DeviceMockAdaptor *>(device_->adaptor_.get()),
358 EmitBoolChanged(flimflam::kPoweredProperty, false));
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700359 EXPECT_CALL(rtnl_handler_, SetInterfaceFlags(_, 0, IFF_UP));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500360 device_->SetEnabled(false);
361 device_->OnEnabledStateChanged(ResultCallback(), Error());
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700362
363 EXPECT_FALSE(device_->ipconfig_.get());
364 EXPECT_FALSE(device_->selected_service_.get());
365}
366
Paul Stewartc681fa02012-03-02 19:40:04 -0800367class DevicePortalDetectionTest : public DeviceTest {
368 public:
369 DevicePortalDetectionTest()
370 : connection_(new StrictMock<MockConnection>(&device_info_)),
371 manager_(control_interface(),
372 dispatcher(),
373 metrics(),
374 glib()),
375 service_(new StrictMock<MockService>(control_interface(),
376 dispatcher(),
377 metrics(),
378 &manager_)),
379 portal_detector_(new StrictMock<MockPortalDetector>(connection_)) {}
380 virtual ~DevicePortalDetectionTest() {}
381 virtual void SetUp() {
382 DeviceTest::SetUp();
383 SelectService(service_);
384 SetConnection(connection_.get());
385 device_->portal_detector_.reset(portal_detector_); // Passes ownership.
386 device_->manager_ = &manager_;
387 }
388
389 protected:
Thieu Le85e050b2012-03-13 15:04:38 -0700390 static const int kPortalAttempts;
391
Paul Stewartc681fa02012-03-02 19:40:04 -0800392 bool StartPortalDetection() { return device_->StartPortalDetection(); }
393 void StopPortalDetection() { device_->StopPortalDetection(); }
394
395 void PortalDetectorCallback(const PortalDetector::Result &result) {
396 device_->PortalDetectorCallback(result);
397 }
398 bool RequestPortalDetection() {
399 return device_->RequestPortalDetection();
400 }
401 void SetServiceConnectedState(Service::ConnectState state) {
402 device_->SetServiceConnectedState(state);
403 }
404 void ExpectPortalDetectorReset() {
405 EXPECT_FALSE(device_->portal_detector_.get());
406 }
407 void ExpectPortalDetectorSet() {
408 EXPECT_TRUE(device_->portal_detector_.get());
409 }
410 void ExpectPortalDetectorIsMock() {
411 EXPECT_EQ(portal_detector_, device_->portal_detector_.get());
412 }
413 scoped_refptr<MockConnection> connection_;
414 StrictMock<MockManager> manager_;
415 scoped_refptr<MockService> service_;
416
417 // Used only for EXPECT_CALL(). Object is owned by device.
418 MockPortalDetector *portal_detector_;
419};
420
Thieu Le85e050b2012-03-13 15:04:38 -0700421const int DevicePortalDetectionTest::kPortalAttempts = 2;
422
Paul Stewartd215af62012-04-24 23:25:50 -0700423TEST_F(DevicePortalDetectionTest, ServicePortalDetectionDisabled) {
424 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
425 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800426 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800427 .WillRepeatedly(Return(true));
Paul Stewartd215af62012-04-24 23:25:50 -0700428 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
429 EXPECT_FALSE(StartPortalDetection());
430}
431
432TEST_F(DevicePortalDetectionTest, TechnologyPortalDetectionDisabled) {
433 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
434 .WillOnce(Return(false));
435 EXPECT_CALL(*service_.get(), IsConnected())
436 .WillRepeatedly(Return(true));
437 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
438 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800439 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800440 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800441 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800442 EXPECT_FALSE(StartPortalDetection());
443}
444
Paul Stewartc681fa02012-03-02 19:40:04 -0800445TEST_F(DevicePortalDetectionTest, PortalDetectionProxyConfig) {
Paul Stewartd215af62012-04-24 23:25:50 -0700446 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
447 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800448 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800449 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800450 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800451 .WillOnce(Return(true));
Paul Stewartd215af62012-04-24 23:25:50 -0700452 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
453 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800454 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800455 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800456 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800457 EXPECT_FALSE(StartPortalDetection());
458}
459
Paul Stewartc681fa02012-03-02 19:40:04 -0800460TEST_F(DevicePortalDetectionTest, PortalDetectionBadUrl) {
Paul Stewartd215af62012-04-24 23:25:50 -0700461 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
462 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800463 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800464 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800465 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800466 .WillOnce(Return(false));
Paul Stewartd215af62012-04-24 23:25:50 -0700467 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
468 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800469 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800470 .WillOnce(Return(true));
471 const string portal_url;
Paul Stewartc681fa02012-03-02 19:40:04 -0800472 EXPECT_CALL(manager_, GetPortalCheckURL())
Paul Stewart20088d82012-02-16 06:58:55 -0800473 .WillRepeatedly(ReturnRef(portal_url));
Paul Stewartc681fa02012-03-02 19:40:04 -0800474 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800475 EXPECT_FALSE(StartPortalDetection());
476}
477
Paul Stewartc681fa02012-03-02 19:40:04 -0800478TEST_F(DevicePortalDetectionTest, PortalDetectionStart) {
Paul Stewartd215af62012-04-24 23:25:50 -0700479 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
480 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800481 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800482 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800483 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800484 .WillOnce(Return(false));
Paul Stewartd215af62012-04-24 23:25:50 -0700485 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
486 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800487 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800488 .WillOnce(Return(true));
489 const string portal_url(PortalDetector::kDefaultURL);
Paul Stewartc681fa02012-03-02 19:40:04 -0800490 EXPECT_CALL(manager_, GetPortalCheckURL())
Paul Stewart20088d82012-02-16 06:58:55 -0800491 .WillRepeatedly(ReturnRef(portal_url));
Paul Stewartc681fa02012-03-02 19:40:04 -0800492 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline))
Paul Stewart20088d82012-02-16 06:58:55 -0800493 .Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800494 const string kInterfaceName("int0");
Paul Stewartc681fa02012-03-02 19:40:04 -0800495 EXPECT_CALL(*connection_.get(), interface_name())
496 .WillRepeatedly(ReturnRef(kInterfaceName));
Paul Stewart20088d82012-02-16 06:58:55 -0800497 const vector<string> kDNSServers;
Paul Stewartc681fa02012-03-02 19:40:04 -0800498 EXPECT_CALL(*connection_.get(), dns_servers())
499 .WillRepeatedly(ReturnRef(kDNSServers));
Paul Stewart20088d82012-02-16 06:58:55 -0800500 EXPECT_TRUE(StartPortalDetection());
501
502 // Drop all references to device_info before it falls out of scope.
503 SetConnection(NULL);
504 StopPortalDetection();
505}
506
Paul Stewartc681fa02012-03-02 19:40:04 -0800507TEST_F(DevicePortalDetectionTest, PortalDetectionNonFinal) {
508 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800509 .Times(0);
Paul Stewartc681fa02012-03-02 19:40:04 -0800510 EXPECT_CALL(*service_.get(), SetState(_))
Paul Stewart20088d82012-02-16 06:58:55 -0800511 .Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800512 PortalDetectorCallback(PortalDetector::Result(
513 PortalDetector::kPhaseUnknown,
514 PortalDetector::kStatusFailure,
Thieu Le85e050b2012-03-13 15:04:38 -0700515 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800516 false));
517}
518
Paul Stewartc681fa02012-03-02 19:40:04 -0800519TEST_F(DevicePortalDetectionTest, PortalDetectionFailure) {
520 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800521 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800522 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
Thieu Le85e050b2012-03-13 15:04:38 -0700523 EXPECT_CALL(metrics_,
524 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
525 Metrics::kPortalResultConnectionFailure,
526 Metrics::kPortalResultMax));
527 EXPECT_CALL(metrics_,
528 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
529 _, _, _, _)).Times(0);
530 EXPECT_CALL(metrics_,
531 SendToUMA("Network.Shill.Unknown.PortalAttempts",
532 kPortalAttempts,
533 Metrics::kMetricPortalAttemptsMin,
534 Metrics::kMetricPortalAttemptsMax,
535 Metrics::kMetricPortalAttemptsNumBuckets));
Paul Stewartc681fa02012-03-02 19:40:04 -0800536 EXPECT_CALL(*connection_.get(), is_default())
537 .WillOnce(Return(false));
Paul Stewart20088d82012-02-16 06:58:55 -0800538 PortalDetectorCallback(PortalDetector::Result(
Thieu Le85e050b2012-03-13 15:04:38 -0700539 PortalDetector::kPhaseConnection,
Paul Stewart20088d82012-02-16 06:58:55 -0800540 PortalDetector::kStatusFailure,
Thieu Le85e050b2012-03-13 15:04:38 -0700541 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800542 true));
543}
544
Paul Stewartc681fa02012-03-02 19:40:04 -0800545TEST_F(DevicePortalDetectionTest, PortalDetectionSuccess) {
546 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800547 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800548 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Thieu Le85e050b2012-03-13 15:04:38 -0700549 EXPECT_CALL(metrics_,
550 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
551 Metrics::kPortalResultSuccess,
552 Metrics::kPortalResultMax));
553 EXPECT_CALL(metrics_,
554 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
555 kPortalAttempts,
556 Metrics::kMetricPortalAttemptsToOnlineMin,
557 Metrics::kMetricPortalAttemptsToOnlineMax,
558 Metrics::kMetricPortalAttemptsToOnlineNumBuckets));
559 EXPECT_CALL(metrics_,
560 SendToUMA("Network.Shill.Unknown.PortalAttempts",
561 _, _, _, _)).Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800562 PortalDetectorCallback(PortalDetector::Result(
Thieu Le85e050b2012-03-13 15:04:38 -0700563 PortalDetector::kPhaseContent,
Paul Stewart20088d82012-02-16 06:58:55 -0800564 PortalDetector::kStatusSuccess,
Thieu Le85e050b2012-03-13 15:04:38 -0700565 kPortalAttempts,
566 true));
567}
568
569TEST_F(DevicePortalDetectionTest, PortalDetectionSuccessAfterFailure) {
570 EXPECT_CALL(*service_.get(), IsConnected())
571 .WillRepeatedly(Return(true));
572 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
573 EXPECT_CALL(metrics_,
574 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
575 Metrics::kPortalResultConnectionFailure,
576 Metrics::kPortalResultMax));
577 EXPECT_CALL(metrics_,
578 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
579 _, _, _, _)).Times(0);
580 EXPECT_CALL(metrics_,
581 SendToUMA("Network.Shill.Unknown.PortalAttempts",
582 kPortalAttempts,
583 Metrics::kMetricPortalAttemptsMin,
584 Metrics::kMetricPortalAttemptsMax,
585 Metrics::kMetricPortalAttemptsNumBuckets));
586 EXPECT_CALL(*connection_.get(), is_default())
587 .WillOnce(Return(false));
588 PortalDetectorCallback(PortalDetector::Result(
589 PortalDetector::kPhaseConnection,
590 PortalDetector::kStatusFailure,
591 kPortalAttempts,
592 true));
593 Mock::VerifyAndClearExpectations(&metrics_);
594
595 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
596 EXPECT_CALL(metrics_,
597 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
598 Metrics::kPortalResultSuccess,
599 Metrics::kPortalResultMax));
600 EXPECT_CALL(metrics_,
601 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
602 kPortalAttempts * 2,
603 Metrics::kMetricPortalAttemptsToOnlineMin,
604 Metrics::kMetricPortalAttemptsToOnlineMax,
605 Metrics::kMetricPortalAttemptsToOnlineNumBuckets));
606 EXPECT_CALL(metrics_,
607 SendToUMA("Network.Shill.Unknown.PortalAttempts",
608 _, _, _, _)).Times(0);
609 PortalDetectorCallback(PortalDetector::Result(
610 PortalDetector::kPhaseContent,
611 PortalDetector::kStatusSuccess,
612 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800613 true));
614}
615
Paul Stewartc681fa02012-03-02 19:40:04 -0800616TEST_F(DevicePortalDetectionTest, RequestPortalDetection) {
617 EXPECT_CALL(*service_.get(), state())
618 .WillOnce(Return(Service::kStateOnline))
619 .WillRepeatedly(Return(Service::kStatePortal));
620 EXPECT_FALSE(RequestPortalDetection());
621
622 EXPECT_CALL(*connection_.get(), is_default())
623 .WillOnce(Return(false))
624 .WillRepeatedly(Return(true));
625 EXPECT_FALSE(RequestPortalDetection());
626
627 EXPECT_CALL(*portal_detector_, IsInProgress())
628 .WillOnce(Return(true));
629 // Portal detection already running.
630 EXPECT_TRUE(RequestPortalDetection());
631
632 // Make sure our running mock portal detector was not replaced.
633 ExpectPortalDetectorIsMock();
634
635 // Throw away our pre-fabricated portal detector, and have the device create
636 // a new one.
637 StopPortalDetection();
Paul Stewartd215af62012-04-24 23:25:50 -0700638 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
639 .WillRepeatedly(Return(false));
640 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
641 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800642 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
643 .WillRepeatedly(Return(true));
644 EXPECT_CALL(*service_.get(), HasProxyConfig())
645 .WillRepeatedly(Return(false));
646 const string kPortalCheckURL("http://portal");
647 EXPECT_CALL(manager_, GetPortalCheckURL())
648 .WillOnce(ReturnRef(kPortalCheckURL));
649 const string kInterfaceName("int0");
650 EXPECT_CALL(*connection_.get(), interface_name())
651 .WillRepeatedly(ReturnRef(kInterfaceName));
652 const vector<string> kDNSServers;
653 EXPECT_CALL(*connection_.get(), dns_servers())
654 .WillRepeatedly(ReturnRef(kDNSServers));
655 EXPECT_TRUE(RequestPortalDetection());
656}
657
658TEST_F(DevicePortalDetectionTest, NotConnected) {
659 EXPECT_CALL(*service_.get(), IsConnected())
660 .WillOnce(Return(false));
661 SetServiceConnectedState(Service::kStatePortal);
662 // We don't check for the portal detector to be reset here, because
663 // it would have been reset as a part of disconnection.
664}
665
666TEST_F(DevicePortalDetectionTest, NotPortal) {
667 EXPECT_CALL(*service_.get(), IsConnected())
668 .WillOnce(Return(true));
669 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
670 SetServiceConnectedState(Service::kStateOnline);
671 ExpectPortalDetectorReset();
672}
673
674TEST_F(DevicePortalDetectionTest, NotDefault) {
675 EXPECT_CALL(*service_.get(), IsConnected())
676 .WillOnce(Return(true));
677 EXPECT_CALL(*connection_.get(), is_default())
678 .WillOnce(Return(false));
679 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
680 SetServiceConnectedState(Service::kStatePortal);
681 ExpectPortalDetectorReset();
682}
683
684TEST_F(DevicePortalDetectionTest, PortalIntervalIsZero) {
685 EXPECT_CALL(*service_.get(), IsConnected())
686 .WillOnce(Return(true));
687 EXPECT_CALL(*connection_.get(), is_default())
688 .WillOnce(Return(true));
689 EXPECT_CALL(manager_, GetPortalCheckInterval())
690 .WillOnce(Return(0));
691 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
692 SetServiceConnectedState(Service::kStatePortal);
693 ExpectPortalDetectorReset();
694}
695
696TEST_F(DevicePortalDetectionTest, RestartPortalDetection) {
697 EXPECT_CALL(*service_.get(), IsConnected())
698 .WillOnce(Return(true));
699 EXPECT_CALL(*connection_.get(), is_default())
700 .WillOnce(Return(true));
701 const int kPortalDetectionInterval = 10;
702 EXPECT_CALL(manager_, GetPortalCheckInterval())
703 .Times(AtLeast(1))
704 .WillRepeatedly(Return(kPortalDetectionInterval));
705 const string kPortalCheckURL("http://portal");
706 EXPECT_CALL(manager_, GetPortalCheckURL())
707 .WillOnce(ReturnRef(kPortalCheckURL));
708 EXPECT_CALL(*portal_detector_, StartAfterDelay(kPortalCheckURL,
709 kPortalDetectionInterval))
710 .WillOnce(Return(true));
711 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
712 SetServiceConnectedState(Service::kStatePortal);
713 ExpectPortalDetectorSet();
714}
715
Darin Petkovafa6fc42011-06-21 16:21:08 -0700716} // namespace shill