blob: 07c98270d2e547f9642c0b019caba7686c981ffd [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"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070028#include "shill/mock_glib.h"
Chris Masone34af2182011-08-22 11:59:36 -070029#include "shill/mock_ipconfig.h"
Paul Stewart20088d82012-02-16 06:58:55 -080030#include "shill/mock_manager.h"
Thieu Le85e050b2012-03-13 15:04:38 -070031#include "shill/mock_metrics.h"
Paul Stewartc681fa02012-03-02 19:40:04 -080032#include "shill/mock_portal_detector.h"
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -070033#include "shill/mock_rtnl_handler.h"
Paul Stewart03dba0b2011-08-22 16:32:45 -070034#include "shill/mock_service.h"
Chris Masone5dec5f42011-07-22 14:07:55 -070035#include "shill/mock_store.h"
Paul Stewart20088d82012-02-16 06:58:55 -080036#include "shill/portal_detector.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070037#include "shill/property_store_unittest.h"
Gaurav Shah435de2c2011-11-17 19:01:07 -080038#include "shill/technology.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070039
40using std::map;
41using std::string;
42using std::vector;
43using ::testing::_;
Chris Masone5dec5f42011-07-22 14:07:55 -070044using ::testing::AtLeast;
Thieu Le85e050b2012-03-13 15:04:38 -070045using ::testing::Mock;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070046using ::testing::NiceMock;
47using ::testing::Return;
Paul Stewart20088d82012-02-16 06:58:55 -080048using ::testing::ReturnRef;
Paul Stewart03dba0b2011-08-22 16:32:45 -070049using ::testing::StrictMock;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070050using ::testing::Test;
Chris Masone34af2182011-08-22 11:59:36 -070051using ::testing::Values;
Darin Petkovafa6fc42011-06-21 16:21:08 -070052
53namespace shill {
54
Eric Shienbrood9a245532012-03-07 14:20:39 -050055class TestDevice : public Device {
56 public:
57 TestDevice(ControlInterface *control_interface,
58 EventDispatcher *dispatcher,
59 Metrics *metrics,
60 Manager *manager,
61 const std::string &link_name,
62 const std::string &address,
63 int interface_index,
64 Technology::Identifier technology)
65 : Device(control_interface, dispatcher, metrics, manager, link_name,
66 address, interface_index, technology) {}
67 ~TestDevice() {}
68 virtual void Start(Error *error,
Jason Glasgow4a490792012-04-10 15:02:05 -040069 const EnabledStateChangedCallback &callback) {
70 DCHECK(error);
71 }
Eric Shienbrood9a245532012-03-07 14:20:39 -050072 virtual void Stop(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};
77
Chris Masone3bd3c8c2011-06-13 08:20:26 -070078class DeviceTest : public PropertyStoreTest {
Darin Petkovafa6fc42011-06-21 16:21:08 -070079 public:
80 DeviceTest()
Eric Shienbrood9a245532012-03-07 14:20:39 -050081 : device_(new TestDevice(control_interface(),
82 dispatcher(),
83 NULL,
84 manager(),
85 kDeviceName,
86 kDeviceAddress,
87 kDeviceInterfaceIndex,
88 Technology::kUnknown)),
Paul Stewartc681fa02012-03-02 19:40:04 -080089 device_info_(control_interface(), NULL, NULL, NULL) {
Chris Masone2176a882011-09-14 22:29:15 -070090 DHCPProvider::GetInstance()->glib_ = glib();
91 DHCPProvider::GetInstance()->control_interface_ = control_interface();
Darin Petkovafa6fc42011-06-21 16:21:08 -070092 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -070093 virtual ~DeviceTest() {}
Darin Petkovafa6fc42011-06-21 16:21:08 -070094
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -070095 virtual void SetUp() {
Thieu Le85e050b2012-03-13 15:04:38 -070096 device_->metrics_ = &metrics_;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -070097 device_->rtnl_handler_ = &rtnl_handler_;
98 }
99
Darin Petkovafa6fc42011-06-21 16:21:08 -0700100 protected:
Chris Masone626719f2011-08-18 16:58:48 -0700101 static const char kDeviceName[];
102 static const char kDeviceAddress[];
Thieu Lefb46caf2012-03-08 11:57:15 -0800103 static const int kDeviceInterfaceIndex;
Chris Masone626719f2011-08-18 16:58:48 -0700104
Darin Petkov79d74c92012-03-07 17:20:32 +0100105 void OnIPConfigUpdated(const IPConfigRefPtr &ipconfig, bool success) {
106 device_->OnIPConfigUpdated(ipconfig, success);
Paul Stewart20088d82012-02-16 06:58:55 -0800107 }
108
109 void SelectService(const ServiceRefPtr service) {
110 device_->SelectService(service);
111 }
112
Paul Stewart20088d82012-02-16 06:58:55 -0800113 void SetConnection(ConnectionRefPtr connection) {
114 device_->connection_ = connection;
115 }
116
Darin Petkovafa6fc42011-06-21 16:21:08 -0700117 MockControl control_interface_;
118 DeviceRefPtr device_;
Paul Stewartc681fa02012-03-02 19:40:04 -0800119 MockDeviceInfo device_info_;
Thieu Le85e050b2012-03-13 15:04:38 -0700120 MockMetrics metrics_;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700121 StrictMock<MockRTNLHandler> rtnl_handler_;
Darin Petkovafa6fc42011-06-21 16:21:08 -0700122};
123
Chris Masone626719f2011-08-18 16:58:48 -0700124const char DeviceTest::kDeviceName[] = "testdevice";
125const char DeviceTest::kDeviceAddress[] = "address";
Thieu Lefb46caf2012-03-08 11:57:15 -0800126const int DeviceTest::kDeviceInterfaceIndex = 0;
Chris Masone626719f2011-08-18 16:58:48 -0700127
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700128TEST_F(DeviceTest, Contains) {
mukesh agrawalde29fa82011-09-16 16:16:36 -0700129 EXPECT_TRUE(device_->store().Contains(flimflam::kNameProperty));
130 EXPECT_FALSE(device_->store().Contains(""));
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700131}
132
Chris Masonea8a2c252011-06-27 22:16:30 -0700133TEST_F(DeviceTest, GetProperties) {
134 map<string, ::DBus::Variant> props;
135 Error error(Error::kInvalidProperty, "");
Eric Shienbrood9a245532012-03-07 14:20:39 -0500136 ::DBus::Error dbus_error;
137 DBusAdaptor::GetProperties(device_->store(), &props, &dbus_error);
138 ASSERT_FALSE(props.find(flimflam::kNameProperty) == props.end());
139 EXPECT_EQ(props[flimflam::kNameProperty].reader().get_string(),
140 string(kDeviceName));
Chris Masonea8a2c252011-06-27 22:16:30 -0700141}
142
Eric Shienbrood9a245532012-03-07 14:20:39 -0500143// Note: there are currently no writeable Device properties that
144// aren't registered in a subclass.
145TEST_F(DeviceTest, SetReadOnlyProperty) {
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700146 ::DBus::Error error;
Chris Masoneb925cc82011-06-22 15:39:57 -0700147 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800148 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
149 flimflam::kAddressProperty,
150 PropertyStoreTest::kStringV,
151 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700152 EXPECT_EQ(invalid_args(), error.name());
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700153}
154
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800155TEST_F(DeviceTest, ClearReadOnlyProperty) {
156 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800157 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
158 flimflam::kAddressProperty,
159 PropertyStoreTest::kStringV,
160 &error));
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800161}
162
163TEST_F(DeviceTest, ClearReadOnlyDerivedProperty) {
164 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800165 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
166 flimflam::kIPConfigsProperty,
167 PropertyStoreTest::kStringsV,
168 &error));
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800169}
170
Darin Petkovafa6fc42011-06-21 16:21:08 -0700171TEST_F(DeviceTest, TechnologyIs) {
Paul Stewartfdd16072011-09-16 12:41:35 -0700172 EXPECT_FALSE(device_->TechnologyIs(Technology::kEthernet));
Darin Petkovafa6fc42011-06-21 16:21:08 -0700173}
174
175TEST_F(DeviceTest, DestroyIPConfig) {
176 ASSERT_FALSE(device_->ipconfig_.get());
Chris Masone2176a882011-09-14 22:29:15 -0700177 device_->ipconfig_ = new IPConfig(control_interface(), kDeviceName);
Darin Petkovafa6fc42011-06-21 16:21:08 -0700178 device_->DestroyIPConfig();
179 ASSERT_FALSE(device_->ipconfig_.get());
180}
181
182TEST_F(DeviceTest, DestroyIPConfigNULL) {
183 ASSERT_FALSE(device_->ipconfig_.get());
184 device_->DestroyIPConfig();
185 ASSERT_FALSE(device_->ipconfig_.get());
186}
187
Paul Stewart2bf1d352011-12-06 15:02:55 -0800188TEST_F(DeviceTest, AcquireIPConfig) {
Chris Masone2176a882011-09-14 22:29:15 -0700189 device_->ipconfig_ = new IPConfig(control_interface(), "randomname");
190 EXPECT_CALL(*glib(), SpawnAsync(_, _, _, _, _, _, _, _))
Darin Petkovafa6fc42011-06-21 16:21:08 -0700191 .WillOnce(Return(false));
Paul Stewart2bf1d352011-12-06 15:02:55 -0800192 EXPECT_FALSE(device_->AcquireIPConfig());
Darin Petkovafa6fc42011-06-21 16:21:08 -0700193 ASSERT_TRUE(device_->ipconfig_.get());
194 EXPECT_EQ(kDeviceName, device_->ipconfig_->device_name());
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500195 EXPECT_FALSE(device_->ipconfig_->update_callback_.is_null());
Darin Petkovafa6fc42011-06-21 16:21:08 -0700196}
197
Chris Masone5dec5f42011-07-22 14:07:55 -0700198TEST_F(DeviceTest, Load) {
199 NiceMock<MockStore> storage;
200 const string id = device_->GetStorageIdentifier();
201 EXPECT_CALL(storage, ContainsGroup(id)).WillOnce(Return(true));
202 EXPECT_CALL(storage, GetBool(id, _, _))
203 .Times(AtLeast(1))
204 .WillRepeatedly(Return(true));
205 EXPECT_TRUE(device_->Load(&storage));
206}
207
208TEST_F(DeviceTest, Save) {
209 NiceMock<MockStore> storage;
210 const string id = device_->GetStorageIdentifier();
Chris Masone5dec5f42011-07-22 14:07:55 -0700211 EXPECT_CALL(storage, SetString(id, _, _))
212 .Times(AtLeast(1))
213 .WillRepeatedly(Return(true));
214 EXPECT_CALL(storage, SetBool(id, _, _))
215 .Times(AtLeast(1))
216 .WillRepeatedly(Return(true));
Chris Masone2176a882011-09-14 22:29:15 -0700217 scoped_refptr<MockIPConfig> ipconfig = new MockIPConfig(control_interface(),
Chris Masone34af2182011-08-22 11:59:36 -0700218 kDeviceName);
219 EXPECT_CALL(*ipconfig.get(), Save(_, _))
220 .WillOnce(Return(true));
221 device_->ipconfig_ = ipconfig;
Chris Masone5dec5f42011-07-22 14:07:55 -0700222 EXPECT_TRUE(device_->Save(&storage));
223}
224
Chris Masone34af2182011-08-22 11:59:36 -0700225TEST_F(DeviceTest, StorageIdGeneration) {
226 string to_process("/device/stuff/0");
227 ControlInterface::RpcIdToStorageId(&to_process);
228 EXPECT_TRUE(isalpha(to_process[0]));
229 EXPECT_EQ(string::npos, to_process.find('/'));
230}
231
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800232MATCHER(IsNullRefPtr, "") {
233 return !arg;
234}
235
236MATCHER(NotNullRefPtr, "") {
237 return arg;
238}
239
Paul Stewart03dba0b2011-08-22 16:32:45 -0700240TEST_F(DeviceTest, SelectedService) {
241 EXPECT_FALSE(device_->selected_service_.get());
242 device_->SetServiceState(Service::kStateAssociating);
243 scoped_refptr<MockService> service(
Chris Masone2176a882011-09-14 22:29:15 -0700244 new StrictMock<MockService>(control_interface(),
245 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800246 metrics(),
Chris Masone9d779932011-08-25 16:33:41 -0700247 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800248 SelectService(service);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700249 EXPECT_TRUE(device_->selected_service_.get() == service.get());
250
251 EXPECT_CALL(*service.get(), SetState(Service::kStateConfiguring));
252 device_->SetServiceState(Service::kStateConfiguring);
253 EXPECT_CALL(*service.get(), SetFailure(Service::kFailureOutOfRange));
254 device_->SetServiceFailure(Service::kFailureOutOfRange);
255
256 // Service should be returned to "Idle" state
257 EXPECT_CALL(*service.get(), state())
258 .WillOnce(Return(Service::kStateUnknown));
259 EXPECT_CALL(*service.get(), SetState(Service::kStateIdle));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800260 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Paul Stewart20088d82012-02-16 06:58:55 -0800261 SelectService(NULL);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700262
263 // A service in the "Failure" state should not be reset to "Idle"
Paul Stewart20088d82012-02-16 06:58:55 -0800264 SelectService(service);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700265 EXPECT_CALL(*service.get(), state())
266 .WillOnce(Return(Service::kStateFailure));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800267 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Paul Stewart20088d82012-02-16 06:58:55 -0800268 SelectService(NULL);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700269}
270
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800271TEST_F(DeviceTest, IPConfigUpdatedFailure) {
272 scoped_refptr<MockService> service(
273 new StrictMock<MockService>(control_interface(),
274 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800275 metrics(),
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800276 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800277 SelectService(service);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800278 EXPECT_CALL(*service.get(), SetState(Service::kStateDisconnected));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800279 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Darin Petkov79d74c92012-03-07 17:20:32 +0100280 OnIPConfigUpdated(NULL, false);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800281}
282
283TEST_F(DeviceTest, IPConfigUpdatedSuccess) {
284 scoped_refptr<MockService> service(
285 new StrictMock<MockService>(control_interface(),
286 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800287 metrics(),
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800288 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800289 SelectService(service);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800290 scoped_refptr<MockIPConfig> ipconfig = new MockIPConfig(control_interface(),
291 kDeviceName);
292 EXPECT_CALL(*service.get(), SetState(Service::kStateConnected));
Paul Stewart20088d82012-02-16 06:58:55 -0800293 EXPECT_CALL(*service.get(), IsConnected())
294 .WillRepeatedly(Return(true));
Paul Stewartd215af62012-04-24 23:25:50 -0700295 EXPECT_CALL(*service.get(), IsPortalDetectionDisabled())
296 .WillRepeatedly(Return(true));
Paul Stewart20088d82012-02-16 06:58:55 -0800297 EXPECT_CALL(*service.get(), SetState(Service::kStateOnline));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800298 EXPECT_CALL(*service.get(), SetConnection(NotNullRefPtr()));
Darin Petkov79d74c92012-03-07 17:20:32 +0100299 OnIPConfigUpdated(ipconfig.get(), true);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800300}
301
Thieu Lefb46caf2012-03-08 11:57:15 -0800302TEST_F(DeviceTest, Start) {
Paul Stewart8c116a92012-05-02 18:30:03 -0700303 EXPECT_FALSE(device_->running_);
304 EXPECT_FALSE(device_->enabled_);
305 EXPECT_FALSE(device_->enabled_pending_);
Eric Shienbrood9a245532012-03-07 14:20:39 -0500306 device_->SetEnabled(true);
Paul Stewart8c116a92012-05-02 18:30:03 -0700307 EXPECT_TRUE(device_->running_);
308 EXPECT_TRUE(device_->enabled_pending_);
Thieu Lefb46caf2012-03-08 11:57:15 -0800309}
310
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700311TEST_F(DeviceTest, Stop) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500312 device_->enabled_ = true;
313 device_->enabled_pending_ = true;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700314 device_->ipconfig_ = new IPConfig(&control_interface_, kDeviceName);
315 scoped_refptr<MockService> service(
316 new NiceMock<MockService>(&control_interface_,
317 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800318 metrics(),
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700319 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800320 SelectService(service);
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700321
322 EXPECT_CALL(*service.get(), state()).
323 WillRepeatedly(Return(Service::kStateConnected));
324 EXPECT_CALL(*dynamic_cast<DeviceMockAdaptor *>(device_->adaptor_.get()),
325 UpdateEnabled());
Eric Shienbrood9a245532012-03-07 14:20:39 -0500326 EXPECT_CALL(*dynamic_cast<DeviceMockAdaptor *>(device_->adaptor_.get()),
327 EmitBoolChanged(flimflam::kPoweredProperty, false));
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700328 EXPECT_CALL(rtnl_handler_, SetInterfaceFlags(_, 0, IFF_UP));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500329 device_->SetEnabled(false);
330 device_->OnEnabledStateChanged(ResultCallback(), Error());
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700331
332 EXPECT_FALSE(device_->ipconfig_.get());
333 EXPECT_FALSE(device_->selected_service_.get());
334}
335
Paul Stewartc681fa02012-03-02 19:40:04 -0800336
337class DevicePortalDetectionTest : public DeviceTest {
338 public:
339 DevicePortalDetectionTest()
340 : connection_(new StrictMock<MockConnection>(&device_info_)),
341 manager_(control_interface(),
342 dispatcher(),
343 metrics(),
344 glib()),
345 service_(new StrictMock<MockService>(control_interface(),
346 dispatcher(),
347 metrics(),
348 &manager_)),
349 portal_detector_(new StrictMock<MockPortalDetector>(connection_)) {}
350 virtual ~DevicePortalDetectionTest() {}
351 virtual void SetUp() {
352 DeviceTest::SetUp();
353 SelectService(service_);
354 SetConnection(connection_.get());
355 device_->portal_detector_.reset(portal_detector_); // Passes ownership.
356 device_->manager_ = &manager_;
357 }
358
359 protected:
Thieu Le85e050b2012-03-13 15:04:38 -0700360 static const int kPortalAttempts;
361
Paul Stewartc681fa02012-03-02 19:40:04 -0800362 bool StartPortalDetection() { return device_->StartPortalDetection(); }
363 void StopPortalDetection() { device_->StopPortalDetection(); }
364
365 void PortalDetectorCallback(const PortalDetector::Result &result) {
366 device_->PortalDetectorCallback(result);
367 }
368 bool RequestPortalDetection() {
369 return device_->RequestPortalDetection();
370 }
371 void SetServiceConnectedState(Service::ConnectState state) {
372 device_->SetServiceConnectedState(state);
373 }
374 void ExpectPortalDetectorReset() {
375 EXPECT_FALSE(device_->portal_detector_.get());
376 }
377 void ExpectPortalDetectorSet() {
378 EXPECT_TRUE(device_->portal_detector_.get());
379 }
380 void ExpectPortalDetectorIsMock() {
381 EXPECT_EQ(portal_detector_, device_->portal_detector_.get());
382 }
383 scoped_refptr<MockConnection> connection_;
384 StrictMock<MockManager> manager_;
385 scoped_refptr<MockService> service_;
386
387 // Used only for EXPECT_CALL(). Object is owned by device.
388 MockPortalDetector *portal_detector_;
389};
390
Thieu Le85e050b2012-03-13 15:04:38 -0700391const int DevicePortalDetectionTest::kPortalAttempts = 2;
392
Paul Stewartd215af62012-04-24 23:25:50 -0700393TEST_F(DevicePortalDetectionTest, ServicePortalDetectionDisabled) {
394 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
395 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800396 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800397 .WillRepeatedly(Return(true));
Paul Stewartd215af62012-04-24 23:25:50 -0700398 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
399 EXPECT_FALSE(StartPortalDetection());
400}
401
402TEST_F(DevicePortalDetectionTest, TechnologyPortalDetectionDisabled) {
403 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
404 .WillOnce(Return(false));
405 EXPECT_CALL(*service_.get(), IsConnected())
406 .WillRepeatedly(Return(true));
407 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
408 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800409 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800410 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800411 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800412 EXPECT_FALSE(StartPortalDetection());
413}
414
Paul Stewartc681fa02012-03-02 19:40:04 -0800415TEST_F(DevicePortalDetectionTest, PortalDetectionProxyConfig) {
Paul Stewartd215af62012-04-24 23:25:50 -0700416 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
417 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800418 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800419 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800420 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800421 .WillOnce(Return(true));
Paul Stewartd215af62012-04-24 23:25:50 -0700422 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
423 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800424 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800425 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800426 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800427 EXPECT_FALSE(StartPortalDetection());
428}
429
Paul Stewartc681fa02012-03-02 19:40:04 -0800430TEST_F(DevicePortalDetectionTest, PortalDetectionBadUrl) {
Paul Stewartd215af62012-04-24 23:25:50 -0700431 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
432 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800433 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800434 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800435 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800436 .WillOnce(Return(false));
Paul Stewartd215af62012-04-24 23:25:50 -0700437 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(true));
441 const string portal_url;
Paul Stewartc681fa02012-03-02 19:40:04 -0800442 EXPECT_CALL(manager_, GetPortalCheckURL())
Paul Stewart20088d82012-02-16 06:58:55 -0800443 .WillRepeatedly(ReturnRef(portal_url));
Paul Stewartc681fa02012-03-02 19:40:04 -0800444 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800445 EXPECT_FALSE(StartPortalDetection());
446}
447
Paul Stewartc681fa02012-03-02 19:40:04 -0800448TEST_F(DevicePortalDetectionTest, PortalDetectionStart) {
Paul Stewartd215af62012-04-24 23:25:50 -0700449 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
450 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800451 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800452 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800453 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800454 .WillOnce(Return(false));
Paul Stewartd215af62012-04-24 23:25:50 -0700455 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
456 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800457 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800458 .WillOnce(Return(true));
459 const string portal_url(PortalDetector::kDefaultURL);
Paul Stewartc681fa02012-03-02 19:40:04 -0800460 EXPECT_CALL(manager_, GetPortalCheckURL())
Paul Stewart20088d82012-02-16 06:58:55 -0800461 .WillRepeatedly(ReturnRef(portal_url));
Paul Stewartc681fa02012-03-02 19:40:04 -0800462 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline))
Paul Stewart20088d82012-02-16 06:58:55 -0800463 .Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800464 const string kInterfaceName("int0");
Paul Stewartc681fa02012-03-02 19:40:04 -0800465 EXPECT_CALL(*connection_.get(), interface_name())
466 .WillRepeatedly(ReturnRef(kInterfaceName));
Paul Stewart20088d82012-02-16 06:58:55 -0800467 const vector<string> kDNSServers;
Paul Stewartc681fa02012-03-02 19:40:04 -0800468 EXPECT_CALL(*connection_.get(), dns_servers())
469 .WillRepeatedly(ReturnRef(kDNSServers));
Paul Stewart20088d82012-02-16 06:58:55 -0800470 EXPECT_TRUE(StartPortalDetection());
471
472 // Drop all references to device_info before it falls out of scope.
473 SetConnection(NULL);
474 StopPortalDetection();
475}
476
Paul Stewartc681fa02012-03-02 19:40:04 -0800477TEST_F(DevicePortalDetectionTest, PortalDetectionNonFinal) {
478 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800479 .Times(0);
Paul Stewartc681fa02012-03-02 19:40:04 -0800480 EXPECT_CALL(*service_.get(), SetState(_))
Paul Stewart20088d82012-02-16 06:58:55 -0800481 .Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800482 PortalDetectorCallback(PortalDetector::Result(
483 PortalDetector::kPhaseUnknown,
484 PortalDetector::kStatusFailure,
Thieu Le85e050b2012-03-13 15:04:38 -0700485 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800486 false));
487}
488
Paul Stewartc681fa02012-03-02 19:40:04 -0800489TEST_F(DevicePortalDetectionTest, PortalDetectionFailure) {
490 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800491 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800492 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
Thieu Le85e050b2012-03-13 15:04:38 -0700493 EXPECT_CALL(metrics_,
494 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
495 Metrics::kPortalResultConnectionFailure,
496 Metrics::kPortalResultMax));
497 EXPECT_CALL(metrics_,
498 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
499 _, _, _, _)).Times(0);
500 EXPECT_CALL(metrics_,
501 SendToUMA("Network.Shill.Unknown.PortalAttempts",
502 kPortalAttempts,
503 Metrics::kMetricPortalAttemptsMin,
504 Metrics::kMetricPortalAttemptsMax,
505 Metrics::kMetricPortalAttemptsNumBuckets));
Paul Stewartc681fa02012-03-02 19:40:04 -0800506 EXPECT_CALL(*connection_.get(), is_default())
507 .WillOnce(Return(false));
Paul Stewart20088d82012-02-16 06:58:55 -0800508 PortalDetectorCallback(PortalDetector::Result(
Thieu Le85e050b2012-03-13 15:04:38 -0700509 PortalDetector::kPhaseConnection,
Paul Stewart20088d82012-02-16 06:58:55 -0800510 PortalDetector::kStatusFailure,
Thieu Le85e050b2012-03-13 15:04:38 -0700511 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800512 true));
513}
514
Paul Stewartc681fa02012-03-02 19:40:04 -0800515TEST_F(DevicePortalDetectionTest, PortalDetectionSuccess) {
516 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800517 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800518 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Thieu Le85e050b2012-03-13 15:04:38 -0700519 EXPECT_CALL(metrics_,
520 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
521 Metrics::kPortalResultSuccess,
522 Metrics::kPortalResultMax));
523 EXPECT_CALL(metrics_,
524 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
525 kPortalAttempts,
526 Metrics::kMetricPortalAttemptsToOnlineMin,
527 Metrics::kMetricPortalAttemptsToOnlineMax,
528 Metrics::kMetricPortalAttemptsToOnlineNumBuckets));
529 EXPECT_CALL(metrics_,
530 SendToUMA("Network.Shill.Unknown.PortalAttempts",
531 _, _, _, _)).Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800532 PortalDetectorCallback(PortalDetector::Result(
Thieu Le85e050b2012-03-13 15:04:38 -0700533 PortalDetector::kPhaseContent,
Paul Stewart20088d82012-02-16 06:58:55 -0800534 PortalDetector::kStatusSuccess,
Thieu Le85e050b2012-03-13 15:04:38 -0700535 kPortalAttempts,
536 true));
537}
538
539TEST_F(DevicePortalDetectionTest, PortalDetectionSuccessAfterFailure) {
540 EXPECT_CALL(*service_.get(), IsConnected())
541 .WillRepeatedly(Return(true));
542 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
543 EXPECT_CALL(metrics_,
544 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
545 Metrics::kPortalResultConnectionFailure,
546 Metrics::kPortalResultMax));
547 EXPECT_CALL(metrics_,
548 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
549 _, _, _, _)).Times(0);
550 EXPECT_CALL(metrics_,
551 SendToUMA("Network.Shill.Unknown.PortalAttempts",
552 kPortalAttempts,
553 Metrics::kMetricPortalAttemptsMin,
554 Metrics::kMetricPortalAttemptsMax,
555 Metrics::kMetricPortalAttemptsNumBuckets));
556 EXPECT_CALL(*connection_.get(), is_default())
557 .WillOnce(Return(false));
558 PortalDetectorCallback(PortalDetector::Result(
559 PortalDetector::kPhaseConnection,
560 PortalDetector::kStatusFailure,
561 kPortalAttempts,
562 true));
563 Mock::VerifyAndClearExpectations(&metrics_);
564
565 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
566 EXPECT_CALL(metrics_,
567 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
568 Metrics::kPortalResultSuccess,
569 Metrics::kPortalResultMax));
570 EXPECT_CALL(metrics_,
571 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
572 kPortalAttempts * 2,
573 Metrics::kMetricPortalAttemptsToOnlineMin,
574 Metrics::kMetricPortalAttemptsToOnlineMax,
575 Metrics::kMetricPortalAttemptsToOnlineNumBuckets));
576 EXPECT_CALL(metrics_,
577 SendToUMA("Network.Shill.Unknown.PortalAttempts",
578 _, _, _, _)).Times(0);
579 PortalDetectorCallback(PortalDetector::Result(
580 PortalDetector::kPhaseContent,
581 PortalDetector::kStatusSuccess,
582 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800583 true));
584}
585
Paul Stewartc681fa02012-03-02 19:40:04 -0800586TEST_F(DevicePortalDetectionTest, RequestPortalDetection) {
587 EXPECT_CALL(*service_.get(), state())
588 .WillOnce(Return(Service::kStateOnline))
589 .WillRepeatedly(Return(Service::kStatePortal));
590 EXPECT_FALSE(RequestPortalDetection());
591
592 EXPECT_CALL(*connection_.get(), is_default())
593 .WillOnce(Return(false))
594 .WillRepeatedly(Return(true));
595 EXPECT_FALSE(RequestPortalDetection());
596
597 EXPECT_CALL(*portal_detector_, IsInProgress())
598 .WillOnce(Return(true));
599 // Portal detection already running.
600 EXPECT_TRUE(RequestPortalDetection());
601
602 // Make sure our running mock portal detector was not replaced.
603 ExpectPortalDetectorIsMock();
604
605 // Throw away our pre-fabricated portal detector, and have the device create
606 // a new one.
607 StopPortalDetection();
Paul Stewartd215af62012-04-24 23:25:50 -0700608 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
609 .WillRepeatedly(Return(false));
610 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
611 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800612 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
613 .WillRepeatedly(Return(true));
614 EXPECT_CALL(*service_.get(), HasProxyConfig())
615 .WillRepeatedly(Return(false));
616 const string kPortalCheckURL("http://portal");
617 EXPECT_CALL(manager_, GetPortalCheckURL())
618 .WillOnce(ReturnRef(kPortalCheckURL));
619 const string kInterfaceName("int0");
620 EXPECT_CALL(*connection_.get(), interface_name())
621 .WillRepeatedly(ReturnRef(kInterfaceName));
622 const vector<string> kDNSServers;
623 EXPECT_CALL(*connection_.get(), dns_servers())
624 .WillRepeatedly(ReturnRef(kDNSServers));
625 EXPECT_TRUE(RequestPortalDetection());
626}
627
628TEST_F(DevicePortalDetectionTest, NotConnected) {
629 EXPECT_CALL(*service_.get(), IsConnected())
630 .WillOnce(Return(false));
631 SetServiceConnectedState(Service::kStatePortal);
632 // We don't check for the portal detector to be reset here, because
633 // it would have been reset as a part of disconnection.
634}
635
636TEST_F(DevicePortalDetectionTest, NotPortal) {
637 EXPECT_CALL(*service_.get(), IsConnected())
638 .WillOnce(Return(true));
639 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
640 SetServiceConnectedState(Service::kStateOnline);
641 ExpectPortalDetectorReset();
642}
643
644TEST_F(DevicePortalDetectionTest, NotDefault) {
645 EXPECT_CALL(*service_.get(), IsConnected())
646 .WillOnce(Return(true));
647 EXPECT_CALL(*connection_.get(), is_default())
648 .WillOnce(Return(false));
649 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
650 SetServiceConnectedState(Service::kStatePortal);
651 ExpectPortalDetectorReset();
652}
653
654TEST_F(DevicePortalDetectionTest, PortalIntervalIsZero) {
655 EXPECT_CALL(*service_.get(), IsConnected())
656 .WillOnce(Return(true));
657 EXPECT_CALL(*connection_.get(), is_default())
658 .WillOnce(Return(true));
659 EXPECT_CALL(manager_, GetPortalCheckInterval())
660 .WillOnce(Return(0));
661 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
662 SetServiceConnectedState(Service::kStatePortal);
663 ExpectPortalDetectorReset();
664}
665
666TEST_F(DevicePortalDetectionTest, RestartPortalDetection) {
667 EXPECT_CALL(*service_.get(), IsConnected())
668 .WillOnce(Return(true));
669 EXPECT_CALL(*connection_.get(), is_default())
670 .WillOnce(Return(true));
671 const int kPortalDetectionInterval = 10;
672 EXPECT_CALL(manager_, GetPortalCheckInterval())
673 .Times(AtLeast(1))
674 .WillRepeatedly(Return(kPortalDetectionInterval));
675 const string kPortalCheckURL("http://portal");
676 EXPECT_CALL(manager_, GetPortalCheckURL())
677 .WillOnce(ReturnRef(kPortalCheckURL));
678 EXPECT_CALL(*portal_detector_, StartAfterDelay(kPortalCheckURL,
679 kPortalDetectionInterval))
680 .WillOnce(Return(true));
681 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
682 SetServiceConnectedState(Service::kStatePortal);
683 ExpectPortalDetectorSet();
684}
685
Darin Petkovafa6fc42011-06-21 16:21:08 -0700686} // namespace shill