blob: 953cf367a0a3010a6e7eb8eb145220b1c1d8dfe7 [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, DestroyIPConfig) {
177 ASSERT_FALSE(device_->ipconfig_.get());
Chris Masone2176a882011-09-14 22:29:15 -0700178 device_->ipconfig_ = new IPConfig(control_interface(), kDeviceName);
Darin Petkovafa6fc42011-06-21 16:21:08 -0700179 device_->DestroyIPConfig();
180 ASSERT_FALSE(device_->ipconfig_.get());
181}
182
183TEST_F(DeviceTest, DestroyIPConfigNULL) {
184 ASSERT_FALSE(device_->ipconfig_.get());
185 device_->DestroyIPConfig();
186 ASSERT_FALSE(device_->ipconfig_.get());
187}
188
Paul Stewart2bf1d352011-12-06 15:02:55 -0800189TEST_F(DeviceTest, AcquireIPConfig) {
Chris Masone2176a882011-09-14 22:29:15 -0700190 device_->ipconfig_ = new IPConfig(control_interface(), "randomname");
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -0700191 scoped_ptr<MockDHCPProvider> dhcp_provider(new MockDHCPProvider());
192 device_->dhcp_provider_ = dhcp_provider.get();
193 scoped_refptr<MockDHCPConfig> dhcp_config(new MockDHCPConfig(
194 control_interface(),
195 kDeviceName));
196 EXPECT_CALL(*dhcp_provider, CreateConfig(_, _, _, _))
197 .WillOnce(Return(dhcp_config));
198 EXPECT_CALL(*dhcp_config, RequestIP())
Darin Petkovafa6fc42011-06-21 16:21:08 -0700199 .WillOnce(Return(false));
Paul Stewart2bf1d352011-12-06 15:02:55 -0800200 EXPECT_FALSE(device_->AcquireIPConfig());
Darin Petkovafa6fc42011-06-21 16:21:08 -0700201 ASSERT_TRUE(device_->ipconfig_.get());
202 EXPECT_EQ(kDeviceName, device_->ipconfig_->device_name());
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500203 EXPECT_FALSE(device_->ipconfig_->update_callback_.is_null());
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -0700204 device_->dhcp_provider_ = NULL;
Darin Petkovafa6fc42011-06-21 16:21:08 -0700205}
206
Chris Masone5dec5f42011-07-22 14:07:55 -0700207TEST_F(DeviceTest, Load) {
208 NiceMock<MockStore> storage;
209 const string id = device_->GetStorageIdentifier();
210 EXPECT_CALL(storage, ContainsGroup(id)).WillOnce(Return(true));
211 EXPECT_CALL(storage, GetBool(id, _, _))
212 .Times(AtLeast(1))
213 .WillRepeatedly(Return(true));
214 EXPECT_TRUE(device_->Load(&storage));
215}
216
217TEST_F(DeviceTest, Save) {
218 NiceMock<MockStore> storage;
219 const string id = device_->GetStorageIdentifier();
Chris Masone5dec5f42011-07-22 14:07:55 -0700220 EXPECT_CALL(storage, SetString(id, _, _))
221 .Times(AtLeast(1))
222 .WillRepeatedly(Return(true));
223 EXPECT_CALL(storage, SetBool(id, _, _))
224 .Times(AtLeast(1))
225 .WillRepeatedly(Return(true));
Chris Masone2176a882011-09-14 22:29:15 -0700226 scoped_refptr<MockIPConfig> ipconfig = new MockIPConfig(control_interface(),
Chris Masone34af2182011-08-22 11:59:36 -0700227 kDeviceName);
228 EXPECT_CALL(*ipconfig.get(), Save(_, _))
229 .WillOnce(Return(true));
230 device_->ipconfig_ = ipconfig;
Chris Masone5dec5f42011-07-22 14:07:55 -0700231 EXPECT_TRUE(device_->Save(&storage));
232}
233
Chris Masone34af2182011-08-22 11:59:36 -0700234TEST_F(DeviceTest, StorageIdGeneration) {
235 string to_process("/device/stuff/0");
236 ControlInterface::RpcIdToStorageId(&to_process);
237 EXPECT_TRUE(isalpha(to_process[0]));
238 EXPECT_EQ(string::npos, to_process.find('/'));
239}
240
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800241MATCHER(IsNullRefPtr, "") {
242 return !arg;
243}
244
245MATCHER(NotNullRefPtr, "") {
246 return arg;
247}
248
Paul Stewart03dba0b2011-08-22 16:32:45 -0700249TEST_F(DeviceTest, SelectedService) {
250 EXPECT_FALSE(device_->selected_service_.get());
251 device_->SetServiceState(Service::kStateAssociating);
252 scoped_refptr<MockService> service(
Chris Masone2176a882011-09-14 22:29:15 -0700253 new StrictMock<MockService>(control_interface(),
254 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800255 metrics(),
Chris Masone9d779932011-08-25 16:33:41 -0700256 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800257 SelectService(service);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700258 EXPECT_TRUE(device_->selected_service_.get() == service.get());
259
260 EXPECT_CALL(*service.get(), SetState(Service::kStateConfiguring));
261 device_->SetServiceState(Service::kStateConfiguring);
262 EXPECT_CALL(*service.get(), SetFailure(Service::kFailureOutOfRange));
263 device_->SetServiceFailure(Service::kFailureOutOfRange);
264
265 // Service should be returned to "Idle" state
266 EXPECT_CALL(*service.get(), state())
267 .WillOnce(Return(Service::kStateUnknown));
268 EXPECT_CALL(*service.get(), SetState(Service::kStateIdle));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800269 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Paul Stewart20088d82012-02-16 06:58:55 -0800270 SelectService(NULL);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700271
272 // A service in the "Failure" state should not be reset to "Idle"
Paul Stewart20088d82012-02-16 06:58:55 -0800273 SelectService(service);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700274 EXPECT_CALL(*service.get(), state())
275 .WillOnce(Return(Service::kStateFailure));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800276 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Paul Stewart20088d82012-02-16 06:58:55 -0800277 SelectService(NULL);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700278}
279
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800280TEST_F(DeviceTest, IPConfigUpdatedFailure) {
281 scoped_refptr<MockService> service(
282 new StrictMock<MockService>(control_interface(),
283 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800284 metrics(),
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800285 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800286 SelectService(service);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800287 EXPECT_CALL(*service.get(), SetState(Service::kStateDisconnected));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800288 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Darin Petkov79d74c92012-03-07 17:20:32 +0100289 OnIPConfigUpdated(NULL, false);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800290}
291
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700292TEST_F(DeviceTest, IPConfigUpdatedFailureWithStatic) {
293 scoped_refptr<MockService> service(
294 new StrictMock<MockService>(control_interface(),
295 dispatcher(),
296 metrics(),
297 manager()));
298 SelectService(service);
299 service->static_ip_parameters_.args_.SetString(
300 flimflam::kAddressProperty, "1.1.1.1");
301 service->static_ip_parameters_.args_.SetInt(flimflam::kPrefixlenProperty, 16);
302 EXPECT_CALL(*service.get(), SetState(_)).Times(0);
303 EXPECT_CALL(*service.get(), SetConnection(_)).Times(0);
304 OnIPConfigUpdated(NULL, false);
305}
306
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800307TEST_F(DeviceTest, IPConfigUpdatedSuccess) {
308 scoped_refptr<MockService> service(
309 new StrictMock<MockService>(control_interface(),
310 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800311 metrics(),
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800312 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800313 SelectService(service);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800314 scoped_refptr<MockIPConfig> ipconfig = new MockIPConfig(control_interface(),
315 kDeviceName);
316 EXPECT_CALL(*service.get(), SetState(Service::kStateConnected));
Paul Stewart20088d82012-02-16 06:58:55 -0800317 EXPECT_CALL(*service.get(), IsConnected())
318 .WillRepeatedly(Return(true));
Paul Stewartd215af62012-04-24 23:25:50 -0700319 EXPECT_CALL(*service.get(), IsPortalDetectionDisabled())
320 .WillRepeatedly(Return(true));
Paul Stewart20088d82012-02-16 06:58:55 -0800321 EXPECT_CALL(*service.get(), SetState(Service::kStateOnline));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800322 EXPECT_CALL(*service.get(), SetConnection(NotNullRefPtr()));
Darin Petkov79d74c92012-03-07 17:20:32 +0100323 OnIPConfigUpdated(ipconfig.get(), true);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800324}
325
Darin Petkove7c6ad32012-06-29 10:22:09 +0200326TEST_F(DeviceTest, SetEnabledPersistent) {
327 EXPECT_FALSE(device_->enabled_);
328 EXPECT_FALSE(device_->enabled_pending_);
329 device_->enabled_persistent_ = false;
330 StrictMock<MockManager> manager(control_interface(),
331 dispatcher(),
332 metrics(),
333 glib());
334 EXPECT_CALL(manager, UpdateDevice(_));
335 device_->manager_ = &manager;
336 Error error;
337 device_->SetEnabledPersistent(true, &error, ResultCallback());
338 EXPECT_TRUE(device_->enabled_persistent_);
339 EXPECT_TRUE(device_->enabled_pending_);
340}
341
Thieu Lefb46caf2012-03-08 11:57:15 -0800342TEST_F(DeviceTest, Start) {
Paul Stewart8c116a92012-05-02 18:30:03 -0700343 EXPECT_FALSE(device_->running_);
344 EXPECT_FALSE(device_->enabled_);
345 EXPECT_FALSE(device_->enabled_pending_);
Eric Shienbrood9a245532012-03-07 14:20:39 -0500346 device_->SetEnabled(true);
Paul Stewart8c116a92012-05-02 18:30:03 -0700347 EXPECT_TRUE(device_->running_);
348 EXPECT_TRUE(device_->enabled_pending_);
Gary Morainbaeefdf2012-04-30 14:53:35 -0700349 device_->OnEnabledStateChanged(ResultCallback(),
350 Error(Error::kOperationFailed));
351 EXPECT_FALSE(device_->enabled_pending_);
Thieu Lefb46caf2012-03-08 11:57:15 -0800352}
353
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700354TEST_F(DeviceTest, Stop) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500355 device_->enabled_ = true;
356 device_->enabled_pending_ = true;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700357 device_->ipconfig_ = new IPConfig(&control_interface_, kDeviceName);
358 scoped_refptr<MockService> service(
359 new NiceMock<MockService>(&control_interface_,
360 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800361 metrics(),
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700362 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800363 SelectService(service);
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700364
365 EXPECT_CALL(*service.get(), state()).
366 WillRepeatedly(Return(Service::kStateConnected));
367 EXPECT_CALL(*dynamic_cast<DeviceMockAdaptor *>(device_->adaptor_.get()),
368 UpdateEnabled());
Eric Shienbrood9a245532012-03-07 14:20:39 -0500369 EXPECT_CALL(*dynamic_cast<DeviceMockAdaptor *>(device_->adaptor_.get()),
370 EmitBoolChanged(flimflam::kPoweredProperty, false));
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700371 EXPECT_CALL(rtnl_handler_, SetInterfaceFlags(_, 0, IFF_UP));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500372 device_->SetEnabled(false);
373 device_->OnEnabledStateChanged(ResultCallback(), Error());
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700374
375 EXPECT_FALSE(device_->ipconfig_.get());
376 EXPECT_FALSE(device_->selected_service_.get());
377}
378
Paul Stewartc681fa02012-03-02 19:40:04 -0800379class DevicePortalDetectionTest : public DeviceTest {
380 public:
381 DevicePortalDetectionTest()
382 : connection_(new StrictMock<MockConnection>(&device_info_)),
383 manager_(control_interface(),
384 dispatcher(),
385 metrics(),
386 glib()),
387 service_(new StrictMock<MockService>(control_interface(),
388 dispatcher(),
389 metrics(),
390 &manager_)),
391 portal_detector_(new StrictMock<MockPortalDetector>(connection_)) {}
392 virtual ~DevicePortalDetectionTest() {}
393 virtual void SetUp() {
394 DeviceTest::SetUp();
395 SelectService(service_);
396 SetConnection(connection_.get());
397 device_->portal_detector_.reset(portal_detector_); // Passes ownership.
398 device_->manager_ = &manager_;
399 }
400
401 protected:
Thieu Le85e050b2012-03-13 15:04:38 -0700402 static const int kPortalAttempts;
403
Paul Stewartc681fa02012-03-02 19:40:04 -0800404 bool StartPortalDetection() { return device_->StartPortalDetection(); }
405 void StopPortalDetection() { device_->StopPortalDetection(); }
406
407 void PortalDetectorCallback(const PortalDetector::Result &result) {
408 device_->PortalDetectorCallback(result);
409 }
410 bool RequestPortalDetection() {
411 return device_->RequestPortalDetection();
412 }
413 void SetServiceConnectedState(Service::ConnectState state) {
414 device_->SetServiceConnectedState(state);
415 }
416 void ExpectPortalDetectorReset() {
417 EXPECT_FALSE(device_->portal_detector_.get());
418 }
419 void ExpectPortalDetectorSet() {
420 EXPECT_TRUE(device_->portal_detector_.get());
421 }
422 void ExpectPortalDetectorIsMock() {
423 EXPECT_EQ(portal_detector_, device_->portal_detector_.get());
424 }
425 scoped_refptr<MockConnection> connection_;
426 StrictMock<MockManager> manager_;
427 scoped_refptr<MockService> service_;
428
429 // Used only for EXPECT_CALL(). Object is owned by device.
430 MockPortalDetector *portal_detector_;
431};
432
Thieu Le85e050b2012-03-13 15:04:38 -0700433const int DevicePortalDetectionTest::kPortalAttempts = 2;
434
Paul Stewartd215af62012-04-24 23:25:50 -0700435TEST_F(DevicePortalDetectionTest, ServicePortalDetectionDisabled) {
436 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
437 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800438 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800439 .WillRepeatedly(Return(true));
Paul Stewartd215af62012-04-24 23:25:50 -0700440 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
441 EXPECT_FALSE(StartPortalDetection());
442}
443
444TEST_F(DevicePortalDetectionTest, TechnologyPortalDetectionDisabled) {
445 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
446 .WillOnce(Return(false));
447 EXPECT_CALL(*service_.get(), IsConnected())
448 .WillRepeatedly(Return(true));
449 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
450 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800451 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800452 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800453 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800454 EXPECT_FALSE(StartPortalDetection());
455}
456
Paul Stewartc681fa02012-03-02 19:40:04 -0800457TEST_F(DevicePortalDetectionTest, PortalDetectionProxyConfig) {
Paul Stewartd215af62012-04-24 23:25:50 -0700458 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
459 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800460 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800461 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800462 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800463 .WillOnce(Return(true));
Paul Stewartd215af62012-04-24 23:25:50 -0700464 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
465 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800466 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800467 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800468 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800469 EXPECT_FALSE(StartPortalDetection());
470}
471
Paul Stewartc681fa02012-03-02 19:40:04 -0800472TEST_F(DevicePortalDetectionTest, PortalDetectionBadUrl) {
Paul Stewartd215af62012-04-24 23:25:50 -0700473 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
474 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800475 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800476 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800477 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800478 .WillOnce(Return(false));
Paul Stewartd215af62012-04-24 23:25:50 -0700479 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
480 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800481 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800482 .WillOnce(Return(true));
483 const string portal_url;
Paul Stewartc681fa02012-03-02 19:40:04 -0800484 EXPECT_CALL(manager_, GetPortalCheckURL())
Paul Stewart20088d82012-02-16 06:58:55 -0800485 .WillRepeatedly(ReturnRef(portal_url));
Paul Stewartc681fa02012-03-02 19:40:04 -0800486 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800487 EXPECT_FALSE(StartPortalDetection());
488}
489
Paul Stewartc681fa02012-03-02 19:40:04 -0800490TEST_F(DevicePortalDetectionTest, PortalDetectionStart) {
Paul Stewartd215af62012-04-24 23:25:50 -0700491 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
492 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800493 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800494 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800495 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800496 .WillOnce(Return(false));
Paul Stewartd215af62012-04-24 23:25:50 -0700497 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
498 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800499 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800500 .WillOnce(Return(true));
501 const string portal_url(PortalDetector::kDefaultURL);
Paul Stewartc681fa02012-03-02 19:40:04 -0800502 EXPECT_CALL(manager_, GetPortalCheckURL())
Paul Stewart20088d82012-02-16 06:58:55 -0800503 .WillRepeatedly(ReturnRef(portal_url));
Paul Stewartc681fa02012-03-02 19:40:04 -0800504 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline))
Paul Stewart20088d82012-02-16 06:58:55 -0800505 .Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800506 const string kInterfaceName("int0");
Paul Stewartc681fa02012-03-02 19:40:04 -0800507 EXPECT_CALL(*connection_.get(), interface_name())
508 .WillRepeatedly(ReturnRef(kInterfaceName));
Paul Stewart20088d82012-02-16 06:58:55 -0800509 const vector<string> kDNSServers;
Paul Stewartc681fa02012-03-02 19:40:04 -0800510 EXPECT_CALL(*connection_.get(), dns_servers())
511 .WillRepeatedly(ReturnRef(kDNSServers));
Paul Stewart20088d82012-02-16 06:58:55 -0800512 EXPECT_TRUE(StartPortalDetection());
513
514 // Drop all references to device_info before it falls out of scope.
515 SetConnection(NULL);
516 StopPortalDetection();
517}
518
Paul Stewartc681fa02012-03-02 19:40:04 -0800519TEST_F(DevicePortalDetectionTest, PortalDetectionNonFinal) {
520 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800521 .Times(0);
Paul Stewartc681fa02012-03-02 19:40:04 -0800522 EXPECT_CALL(*service_.get(), SetState(_))
Paul Stewart20088d82012-02-16 06:58:55 -0800523 .Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800524 PortalDetectorCallback(PortalDetector::Result(
525 PortalDetector::kPhaseUnknown,
526 PortalDetector::kStatusFailure,
Thieu Le85e050b2012-03-13 15:04:38 -0700527 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800528 false));
529}
530
Paul Stewartc681fa02012-03-02 19:40:04 -0800531TEST_F(DevicePortalDetectionTest, PortalDetectionFailure) {
532 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800533 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800534 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
Thieu Le85e050b2012-03-13 15:04:38 -0700535 EXPECT_CALL(metrics_,
536 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
537 Metrics::kPortalResultConnectionFailure,
538 Metrics::kPortalResultMax));
539 EXPECT_CALL(metrics_,
540 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
541 _, _, _, _)).Times(0);
542 EXPECT_CALL(metrics_,
543 SendToUMA("Network.Shill.Unknown.PortalAttempts",
544 kPortalAttempts,
545 Metrics::kMetricPortalAttemptsMin,
546 Metrics::kMetricPortalAttemptsMax,
547 Metrics::kMetricPortalAttemptsNumBuckets));
Paul Stewartc681fa02012-03-02 19:40:04 -0800548 EXPECT_CALL(*connection_.get(), is_default())
549 .WillOnce(Return(false));
Paul Stewart20088d82012-02-16 06:58:55 -0800550 PortalDetectorCallback(PortalDetector::Result(
Thieu Le85e050b2012-03-13 15:04:38 -0700551 PortalDetector::kPhaseConnection,
Paul Stewart20088d82012-02-16 06:58:55 -0800552 PortalDetector::kStatusFailure,
Thieu Le85e050b2012-03-13 15:04:38 -0700553 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800554 true));
555}
556
Paul Stewartc681fa02012-03-02 19:40:04 -0800557TEST_F(DevicePortalDetectionTest, PortalDetectionSuccess) {
558 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800559 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800560 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Thieu Le85e050b2012-03-13 15:04:38 -0700561 EXPECT_CALL(metrics_,
562 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
563 Metrics::kPortalResultSuccess,
564 Metrics::kPortalResultMax));
565 EXPECT_CALL(metrics_,
566 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
567 kPortalAttempts,
568 Metrics::kMetricPortalAttemptsToOnlineMin,
569 Metrics::kMetricPortalAttemptsToOnlineMax,
570 Metrics::kMetricPortalAttemptsToOnlineNumBuckets));
571 EXPECT_CALL(metrics_,
572 SendToUMA("Network.Shill.Unknown.PortalAttempts",
573 _, _, _, _)).Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800574 PortalDetectorCallback(PortalDetector::Result(
Thieu Le85e050b2012-03-13 15:04:38 -0700575 PortalDetector::kPhaseContent,
Paul Stewart20088d82012-02-16 06:58:55 -0800576 PortalDetector::kStatusSuccess,
Thieu Le85e050b2012-03-13 15:04:38 -0700577 kPortalAttempts,
578 true));
579}
580
581TEST_F(DevicePortalDetectionTest, PortalDetectionSuccessAfterFailure) {
582 EXPECT_CALL(*service_.get(), IsConnected())
583 .WillRepeatedly(Return(true));
584 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
585 EXPECT_CALL(metrics_,
586 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
587 Metrics::kPortalResultConnectionFailure,
588 Metrics::kPortalResultMax));
589 EXPECT_CALL(metrics_,
590 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
591 _, _, _, _)).Times(0);
592 EXPECT_CALL(metrics_,
593 SendToUMA("Network.Shill.Unknown.PortalAttempts",
594 kPortalAttempts,
595 Metrics::kMetricPortalAttemptsMin,
596 Metrics::kMetricPortalAttemptsMax,
597 Metrics::kMetricPortalAttemptsNumBuckets));
598 EXPECT_CALL(*connection_.get(), is_default())
599 .WillOnce(Return(false));
600 PortalDetectorCallback(PortalDetector::Result(
601 PortalDetector::kPhaseConnection,
602 PortalDetector::kStatusFailure,
603 kPortalAttempts,
604 true));
605 Mock::VerifyAndClearExpectations(&metrics_);
606
607 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
608 EXPECT_CALL(metrics_,
609 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
610 Metrics::kPortalResultSuccess,
611 Metrics::kPortalResultMax));
612 EXPECT_CALL(metrics_,
613 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
614 kPortalAttempts * 2,
615 Metrics::kMetricPortalAttemptsToOnlineMin,
616 Metrics::kMetricPortalAttemptsToOnlineMax,
617 Metrics::kMetricPortalAttemptsToOnlineNumBuckets));
618 EXPECT_CALL(metrics_,
619 SendToUMA("Network.Shill.Unknown.PortalAttempts",
620 _, _, _, _)).Times(0);
621 PortalDetectorCallback(PortalDetector::Result(
622 PortalDetector::kPhaseContent,
623 PortalDetector::kStatusSuccess,
624 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800625 true));
626}
627
Paul Stewartc681fa02012-03-02 19:40:04 -0800628TEST_F(DevicePortalDetectionTest, RequestPortalDetection) {
629 EXPECT_CALL(*service_.get(), state())
630 .WillOnce(Return(Service::kStateOnline))
631 .WillRepeatedly(Return(Service::kStatePortal));
632 EXPECT_FALSE(RequestPortalDetection());
633
634 EXPECT_CALL(*connection_.get(), is_default())
635 .WillOnce(Return(false))
636 .WillRepeatedly(Return(true));
637 EXPECT_FALSE(RequestPortalDetection());
638
639 EXPECT_CALL(*portal_detector_, IsInProgress())
640 .WillOnce(Return(true));
641 // Portal detection already running.
642 EXPECT_TRUE(RequestPortalDetection());
643
644 // Make sure our running mock portal detector was not replaced.
645 ExpectPortalDetectorIsMock();
646
647 // Throw away our pre-fabricated portal detector, and have the device create
648 // a new one.
649 StopPortalDetection();
Paul Stewartd215af62012-04-24 23:25:50 -0700650 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
651 .WillRepeatedly(Return(false));
652 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
653 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800654 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
655 .WillRepeatedly(Return(true));
656 EXPECT_CALL(*service_.get(), HasProxyConfig())
657 .WillRepeatedly(Return(false));
658 const string kPortalCheckURL("http://portal");
659 EXPECT_CALL(manager_, GetPortalCheckURL())
660 .WillOnce(ReturnRef(kPortalCheckURL));
661 const string kInterfaceName("int0");
662 EXPECT_CALL(*connection_.get(), interface_name())
663 .WillRepeatedly(ReturnRef(kInterfaceName));
664 const vector<string> kDNSServers;
665 EXPECT_CALL(*connection_.get(), dns_servers())
666 .WillRepeatedly(ReturnRef(kDNSServers));
667 EXPECT_TRUE(RequestPortalDetection());
668}
669
670TEST_F(DevicePortalDetectionTest, NotConnected) {
671 EXPECT_CALL(*service_.get(), IsConnected())
672 .WillOnce(Return(false));
673 SetServiceConnectedState(Service::kStatePortal);
674 // We don't check for the portal detector to be reset here, because
675 // it would have been reset as a part of disconnection.
676}
677
678TEST_F(DevicePortalDetectionTest, NotPortal) {
679 EXPECT_CALL(*service_.get(), IsConnected())
680 .WillOnce(Return(true));
681 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
682 SetServiceConnectedState(Service::kStateOnline);
683 ExpectPortalDetectorReset();
684}
685
686TEST_F(DevicePortalDetectionTest, NotDefault) {
687 EXPECT_CALL(*service_.get(), IsConnected())
688 .WillOnce(Return(true));
689 EXPECT_CALL(*connection_.get(), is_default())
690 .WillOnce(Return(false));
691 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
692 SetServiceConnectedState(Service::kStatePortal);
693 ExpectPortalDetectorReset();
694}
695
696TEST_F(DevicePortalDetectionTest, PortalIntervalIsZero) {
697 EXPECT_CALL(*service_.get(), IsConnected())
698 .WillOnce(Return(true));
699 EXPECT_CALL(*connection_.get(), is_default())
700 .WillOnce(Return(true));
701 EXPECT_CALL(manager_, GetPortalCheckInterval())
702 .WillOnce(Return(0));
703 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
704 SetServiceConnectedState(Service::kStatePortal);
705 ExpectPortalDetectorReset();
706}
707
708TEST_F(DevicePortalDetectionTest, RestartPortalDetection) {
709 EXPECT_CALL(*service_.get(), IsConnected())
710 .WillOnce(Return(true));
711 EXPECT_CALL(*connection_.get(), is_default())
712 .WillOnce(Return(true));
713 const int kPortalDetectionInterval = 10;
714 EXPECT_CALL(manager_, GetPortalCheckInterval())
715 .Times(AtLeast(1))
716 .WillRepeatedly(Return(kPortalDetectionInterval));
717 const string kPortalCheckURL("http://portal");
718 EXPECT_CALL(manager_, GetPortalCheckURL())
719 .WillOnce(ReturnRef(kPortalCheckURL));
720 EXPECT_CALL(*portal_detector_, StartAfterDelay(kPortalCheckURL,
721 kPortalDetectionInterval))
722 .WillOnce(Return(true));
723 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
724 SetServiceConnectedState(Service::kStatePortal);
725 ExpectPortalDetectorSet();
726}
727
Darin Petkovafa6fc42011-06-21 16:21:08 -0700728} // namespace shill