blob: fb24466aa31b106390444f3e87c6b3c35b414211 [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"
mukesh agrawalcc0fded2012-05-09 13:40:58 -070038#include "shill/static_ip_parameters.h"
Gaurav Shah435de2c2011-11-17 19:01:07 -080039#include "shill/technology.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070040
41using std::map;
42using std::string;
43using std::vector;
44using ::testing::_;
mukesh agrawalcc0fded2012-05-09 13:40:58 -070045using ::testing::AnyNumber;
Chris Masone5dec5f42011-07-22 14:07:55 -070046using ::testing::AtLeast;
Thieu Le85e050b2012-03-13 15:04:38 -070047using ::testing::Mock;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070048using ::testing::NiceMock;
49using ::testing::Return;
Paul Stewart20088d82012-02-16 06:58:55 -080050using ::testing::ReturnRef;
Paul Stewart03dba0b2011-08-22 16:32:45 -070051using ::testing::StrictMock;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070052using ::testing::Test;
Chris Masone34af2182011-08-22 11:59:36 -070053using ::testing::Values;
Darin Petkovafa6fc42011-06-21 16:21:08 -070054
55namespace shill {
56
Eric Shienbrood9a245532012-03-07 14:20:39 -050057class TestDevice : public Device {
58 public:
59 TestDevice(ControlInterface *control_interface,
60 EventDispatcher *dispatcher,
61 Metrics *metrics,
62 Manager *manager,
63 const std::string &link_name,
64 const std::string &address,
65 int interface_index,
66 Technology::Identifier technology)
67 : Device(control_interface, dispatcher, metrics, manager, link_name,
68 address, interface_index, technology) {}
69 ~TestDevice() {}
70 virtual void Start(Error *error,
Jason Glasgow4a490792012-04-10 15:02:05 -040071 const EnabledStateChangedCallback &callback) {
72 DCHECK(error);
73 }
Eric Shienbrood9a245532012-03-07 14:20:39 -050074 virtual void Stop(Error *error,
Jason Glasgow4a490792012-04-10 15:02:05 -040075 const EnabledStateChangedCallback &callback) {
76 DCHECK(error);
77 }
Eric Shienbrood9a245532012-03-07 14:20:39 -050078};
79
Chris Masone3bd3c8c2011-06-13 08:20:26 -070080class DeviceTest : public PropertyStoreTest {
Darin Petkovafa6fc42011-06-21 16:21:08 -070081 public:
82 DeviceTest()
Eric Shienbrood9a245532012-03-07 14:20:39 -050083 : device_(new TestDevice(control_interface(),
84 dispatcher(),
85 NULL,
86 manager(),
87 kDeviceName,
88 kDeviceAddress,
89 kDeviceInterfaceIndex,
90 Technology::kUnknown)),
Paul Stewartc681fa02012-03-02 19:40:04 -080091 device_info_(control_interface(), NULL, NULL, NULL) {
Chris Masone2176a882011-09-14 22:29:15 -070092 DHCPProvider::GetInstance()->glib_ = glib();
93 DHCPProvider::GetInstance()->control_interface_ = control_interface();
mukesh agrawalcc0fded2012-05-09 13:40:58 -070094 DHCPProvider::GetInstance()->dispatcher_ = dispatcher();
Darin Petkovafa6fc42011-06-21 16:21:08 -070095 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -070096 virtual ~DeviceTest() {}
Darin Petkovafa6fc42011-06-21 16:21:08 -070097
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -070098 virtual void SetUp() {
Thieu Le85e050b2012-03-13 15:04:38 -070099 device_->metrics_ = &metrics_;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700100 device_->rtnl_handler_ = &rtnl_handler_;
101 }
102
Darin Petkovafa6fc42011-06-21 16:21:08 -0700103 protected:
Chris Masone626719f2011-08-18 16:58:48 -0700104 static const char kDeviceName[];
105 static const char kDeviceAddress[];
Thieu Lefb46caf2012-03-08 11:57:15 -0800106 static const int kDeviceInterfaceIndex;
Chris Masone626719f2011-08-18 16:58:48 -0700107
Darin Petkov79d74c92012-03-07 17:20:32 +0100108 void OnIPConfigUpdated(const IPConfigRefPtr &ipconfig, bool success) {
109 device_->OnIPConfigUpdated(ipconfig, success);
Paul Stewart20088d82012-02-16 06:58:55 -0800110 }
111
112 void SelectService(const ServiceRefPtr service) {
113 device_->SelectService(service);
114 }
115
Paul Stewart20088d82012-02-16 06:58:55 -0800116 void SetConnection(ConnectionRefPtr connection) {
117 device_->connection_ = connection;
118 }
119
Darin Petkovafa6fc42011-06-21 16:21:08 -0700120 MockControl control_interface_;
121 DeviceRefPtr device_;
Paul Stewartc681fa02012-03-02 19:40:04 -0800122 MockDeviceInfo device_info_;
Thieu Le85e050b2012-03-13 15:04:38 -0700123 MockMetrics metrics_;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700124 StrictMock<MockRTNLHandler> rtnl_handler_;
Darin Petkovafa6fc42011-06-21 16:21:08 -0700125};
126
Chris Masone626719f2011-08-18 16:58:48 -0700127const char DeviceTest::kDeviceName[] = "testdevice";
128const char DeviceTest::kDeviceAddress[] = "address";
Thieu Lefb46caf2012-03-08 11:57:15 -0800129const int DeviceTest::kDeviceInterfaceIndex = 0;
Chris Masone626719f2011-08-18 16:58:48 -0700130
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700131TEST_F(DeviceTest, Contains) {
mukesh agrawalde29fa82011-09-16 16:16:36 -0700132 EXPECT_TRUE(device_->store().Contains(flimflam::kNameProperty));
133 EXPECT_FALSE(device_->store().Contains(""));
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700134}
135
Chris Masonea8a2c252011-06-27 22:16:30 -0700136TEST_F(DeviceTest, GetProperties) {
137 map<string, ::DBus::Variant> props;
138 Error error(Error::kInvalidProperty, "");
Eric Shienbrood9a245532012-03-07 14:20:39 -0500139 ::DBus::Error dbus_error;
140 DBusAdaptor::GetProperties(device_->store(), &props, &dbus_error);
141 ASSERT_FALSE(props.find(flimflam::kNameProperty) == props.end());
142 EXPECT_EQ(props[flimflam::kNameProperty].reader().get_string(),
143 string(kDeviceName));
Chris Masonea8a2c252011-06-27 22:16:30 -0700144}
145
Eric Shienbrood9a245532012-03-07 14:20:39 -0500146// Note: there are currently no writeable Device properties that
147// aren't registered in a subclass.
148TEST_F(DeviceTest, SetReadOnlyProperty) {
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700149 ::DBus::Error error;
Chris Masoneb925cc82011-06-22 15:39:57 -0700150 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800151 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
152 flimflam::kAddressProperty,
153 PropertyStoreTest::kStringV,
154 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700155 EXPECT_EQ(invalid_args(), error.name());
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700156}
157
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800158TEST_F(DeviceTest, ClearReadOnlyProperty) {
159 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800160 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
161 flimflam::kAddressProperty,
162 PropertyStoreTest::kStringV,
163 &error));
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800164}
165
166TEST_F(DeviceTest, ClearReadOnlyDerivedProperty) {
167 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800168 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
169 flimflam::kIPConfigsProperty,
170 PropertyStoreTest::kStringsV,
171 &error));
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800172}
173
Darin Petkovafa6fc42011-06-21 16:21:08 -0700174TEST_F(DeviceTest, TechnologyIs) {
Paul Stewartfdd16072011-09-16 12:41:35 -0700175 EXPECT_FALSE(device_->TechnologyIs(Technology::kEthernet));
Darin Petkovafa6fc42011-06-21 16:21:08 -0700176}
177
178TEST_F(DeviceTest, DestroyIPConfig) {
179 ASSERT_FALSE(device_->ipconfig_.get());
Chris Masone2176a882011-09-14 22:29:15 -0700180 device_->ipconfig_ = new IPConfig(control_interface(), kDeviceName);
Darin Petkovafa6fc42011-06-21 16:21:08 -0700181 device_->DestroyIPConfig();
182 ASSERT_FALSE(device_->ipconfig_.get());
183}
184
185TEST_F(DeviceTest, DestroyIPConfigNULL) {
186 ASSERT_FALSE(device_->ipconfig_.get());
187 device_->DestroyIPConfig();
188 ASSERT_FALSE(device_->ipconfig_.get());
189}
190
Paul Stewart2bf1d352011-12-06 15:02:55 -0800191TEST_F(DeviceTest, AcquireIPConfig) {
Chris Masone2176a882011-09-14 22:29:15 -0700192 device_->ipconfig_ = new IPConfig(control_interface(), "randomname");
193 EXPECT_CALL(*glib(), SpawnAsync(_, _, _, _, _, _, _, _))
Darin Petkovafa6fc42011-06-21 16:21:08 -0700194 .WillOnce(Return(false));
Paul Stewart2bf1d352011-12-06 15:02:55 -0800195 EXPECT_FALSE(device_->AcquireIPConfig());
Darin Petkovafa6fc42011-06-21 16:21:08 -0700196 ASSERT_TRUE(device_->ipconfig_.get());
197 EXPECT_EQ(kDeviceName, device_->ipconfig_->device_name());
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500198 EXPECT_FALSE(device_->ipconfig_->update_callback_.is_null());
Darin Petkovafa6fc42011-06-21 16:21:08 -0700199}
200
Chris Masone5dec5f42011-07-22 14:07:55 -0700201TEST_F(DeviceTest, Load) {
202 NiceMock<MockStore> storage;
203 const string id = device_->GetStorageIdentifier();
204 EXPECT_CALL(storage, ContainsGroup(id)).WillOnce(Return(true));
205 EXPECT_CALL(storage, GetBool(id, _, _))
206 .Times(AtLeast(1))
207 .WillRepeatedly(Return(true));
208 EXPECT_TRUE(device_->Load(&storage));
209}
210
211TEST_F(DeviceTest, Save) {
212 NiceMock<MockStore> storage;
213 const string id = device_->GetStorageIdentifier();
Chris Masone5dec5f42011-07-22 14:07:55 -0700214 EXPECT_CALL(storage, SetString(id, _, _))
215 .Times(AtLeast(1))
216 .WillRepeatedly(Return(true));
217 EXPECT_CALL(storage, SetBool(id, _, _))
218 .Times(AtLeast(1))
219 .WillRepeatedly(Return(true));
Chris Masone2176a882011-09-14 22:29:15 -0700220 scoped_refptr<MockIPConfig> ipconfig = new MockIPConfig(control_interface(),
Chris Masone34af2182011-08-22 11:59:36 -0700221 kDeviceName);
222 EXPECT_CALL(*ipconfig.get(), Save(_, _))
223 .WillOnce(Return(true));
224 device_->ipconfig_ = ipconfig;
Chris Masone5dec5f42011-07-22 14:07:55 -0700225 EXPECT_TRUE(device_->Save(&storage));
226}
227
Chris Masone34af2182011-08-22 11:59:36 -0700228TEST_F(DeviceTest, StorageIdGeneration) {
229 string to_process("/device/stuff/0");
230 ControlInterface::RpcIdToStorageId(&to_process);
231 EXPECT_TRUE(isalpha(to_process[0]));
232 EXPECT_EQ(string::npos, to_process.find('/'));
233}
234
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800235MATCHER(IsNullRefPtr, "") {
236 return !arg;
237}
238
239MATCHER(NotNullRefPtr, "") {
240 return arg;
241}
242
Paul Stewart03dba0b2011-08-22 16:32:45 -0700243TEST_F(DeviceTest, SelectedService) {
244 EXPECT_FALSE(device_->selected_service_.get());
245 device_->SetServiceState(Service::kStateAssociating);
246 scoped_refptr<MockService> service(
Chris Masone2176a882011-09-14 22:29:15 -0700247 new StrictMock<MockService>(control_interface(),
248 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800249 metrics(),
Chris Masone9d779932011-08-25 16:33:41 -0700250 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800251 SelectService(service);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700252 EXPECT_TRUE(device_->selected_service_.get() == service.get());
253
254 EXPECT_CALL(*service.get(), SetState(Service::kStateConfiguring));
255 device_->SetServiceState(Service::kStateConfiguring);
256 EXPECT_CALL(*service.get(), SetFailure(Service::kFailureOutOfRange));
257 device_->SetServiceFailure(Service::kFailureOutOfRange);
258
259 // Service should be returned to "Idle" state
260 EXPECT_CALL(*service.get(), state())
261 .WillOnce(Return(Service::kStateUnknown));
262 EXPECT_CALL(*service.get(), SetState(Service::kStateIdle));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800263 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Paul Stewart20088d82012-02-16 06:58:55 -0800264 SelectService(NULL);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700265
266 // A service in the "Failure" state should not be reset to "Idle"
Paul Stewart20088d82012-02-16 06:58:55 -0800267 SelectService(service);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700268 EXPECT_CALL(*service.get(), state())
269 .WillOnce(Return(Service::kStateFailure));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800270 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Paul Stewart20088d82012-02-16 06:58:55 -0800271 SelectService(NULL);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700272}
273
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800274TEST_F(DeviceTest, IPConfigUpdatedFailure) {
275 scoped_refptr<MockService> service(
276 new StrictMock<MockService>(control_interface(),
277 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800278 metrics(),
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800279 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800280 SelectService(service);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800281 EXPECT_CALL(*service.get(), SetState(Service::kStateDisconnected));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800282 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Darin Petkov79d74c92012-03-07 17:20:32 +0100283 OnIPConfigUpdated(NULL, false);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800284}
285
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700286TEST_F(DeviceTest, IPConfigUpdatedFailureWithStatic) {
287 scoped_refptr<MockService> service(
288 new StrictMock<MockService>(control_interface(),
289 dispatcher(),
290 metrics(),
291 manager()));
292 SelectService(service);
293 service->static_ip_parameters_.args_.SetString(
294 flimflam::kAddressProperty, "1.1.1.1");
295 service->static_ip_parameters_.args_.SetInt(flimflam::kPrefixlenProperty, 16);
296 EXPECT_CALL(*service.get(), SetState(_)).Times(0);
297 EXPECT_CALL(*service.get(), SetConnection(_)).Times(0);
298 OnIPConfigUpdated(NULL, false);
299}
300
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800301TEST_F(DeviceTest, IPConfigUpdatedSuccess) {
302 scoped_refptr<MockService> service(
303 new StrictMock<MockService>(control_interface(),
304 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800305 metrics(),
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800306 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800307 SelectService(service);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800308 scoped_refptr<MockIPConfig> ipconfig = new MockIPConfig(control_interface(),
309 kDeviceName);
310 EXPECT_CALL(*service.get(), SetState(Service::kStateConnected));
Paul Stewart20088d82012-02-16 06:58:55 -0800311 EXPECT_CALL(*service.get(), IsConnected())
312 .WillRepeatedly(Return(true));
Paul Stewartd215af62012-04-24 23:25:50 -0700313 EXPECT_CALL(*service.get(), IsPortalDetectionDisabled())
314 .WillRepeatedly(Return(true));
Paul Stewart20088d82012-02-16 06:58:55 -0800315 EXPECT_CALL(*service.get(), SetState(Service::kStateOnline));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800316 EXPECT_CALL(*service.get(), SetConnection(NotNullRefPtr()));
Darin Petkov79d74c92012-03-07 17:20:32 +0100317 OnIPConfigUpdated(ipconfig.get(), true);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800318}
319
Thieu Lefb46caf2012-03-08 11:57:15 -0800320TEST_F(DeviceTest, Start) {
Paul Stewart8c116a92012-05-02 18:30:03 -0700321 EXPECT_FALSE(device_->running_);
322 EXPECT_FALSE(device_->enabled_);
323 EXPECT_FALSE(device_->enabled_pending_);
Eric Shienbrood9a245532012-03-07 14:20:39 -0500324 device_->SetEnabled(true);
Paul Stewart8c116a92012-05-02 18:30:03 -0700325 EXPECT_TRUE(device_->running_);
326 EXPECT_TRUE(device_->enabled_pending_);
Gary Morainbaeefdf2012-04-30 14:53:35 -0700327 device_->OnEnabledStateChanged(ResultCallback(),
328 Error(Error::kOperationFailed));
329 EXPECT_FALSE(device_->enabled_pending_);
Thieu Lefb46caf2012-03-08 11:57:15 -0800330}
331
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700332TEST_F(DeviceTest, Stop) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500333 device_->enabled_ = true;
334 device_->enabled_pending_ = true;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700335 device_->ipconfig_ = new IPConfig(&control_interface_, kDeviceName);
336 scoped_refptr<MockService> service(
337 new NiceMock<MockService>(&control_interface_,
338 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800339 metrics(),
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700340 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800341 SelectService(service);
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700342
343 EXPECT_CALL(*service.get(), state()).
344 WillRepeatedly(Return(Service::kStateConnected));
345 EXPECT_CALL(*dynamic_cast<DeviceMockAdaptor *>(device_->adaptor_.get()),
346 UpdateEnabled());
Eric Shienbrood9a245532012-03-07 14:20:39 -0500347 EXPECT_CALL(*dynamic_cast<DeviceMockAdaptor *>(device_->adaptor_.get()),
348 EmitBoolChanged(flimflam::kPoweredProperty, false));
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700349 EXPECT_CALL(rtnl_handler_, SetInterfaceFlags(_, 0, IFF_UP));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500350 device_->SetEnabled(false);
351 device_->OnEnabledStateChanged(ResultCallback(), Error());
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700352
353 EXPECT_FALSE(device_->ipconfig_.get());
354 EXPECT_FALSE(device_->selected_service_.get());
355}
356
Paul Stewartc681fa02012-03-02 19:40:04 -0800357class DevicePortalDetectionTest : public DeviceTest {
358 public:
359 DevicePortalDetectionTest()
360 : connection_(new StrictMock<MockConnection>(&device_info_)),
361 manager_(control_interface(),
362 dispatcher(),
363 metrics(),
364 glib()),
365 service_(new StrictMock<MockService>(control_interface(),
366 dispatcher(),
367 metrics(),
368 &manager_)),
369 portal_detector_(new StrictMock<MockPortalDetector>(connection_)) {}
370 virtual ~DevicePortalDetectionTest() {}
371 virtual void SetUp() {
372 DeviceTest::SetUp();
373 SelectService(service_);
374 SetConnection(connection_.get());
375 device_->portal_detector_.reset(portal_detector_); // Passes ownership.
376 device_->manager_ = &manager_;
377 }
378
379 protected:
Thieu Le85e050b2012-03-13 15:04:38 -0700380 static const int kPortalAttempts;
381
Paul Stewartc681fa02012-03-02 19:40:04 -0800382 bool StartPortalDetection() { return device_->StartPortalDetection(); }
383 void StopPortalDetection() { device_->StopPortalDetection(); }
384
385 void PortalDetectorCallback(const PortalDetector::Result &result) {
386 device_->PortalDetectorCallback(result);
387 }
388 bool RequestPortalDetection() {
389 return device_->RequestPortalDetection();
390 }
391 void SetServiceConnectedState(Service::ConnectState state) {
392 device_->SetServiceConnectedState(state);
393 }
394 void ExpectPortalDetectorReset() {
395 EXPECT_FALSE(device_->portal_detector_.get());
396 }
397 void ExpectPortalDetectorSet() {
398 EXPECT_TRUE(device_->portal_detector_.get());
399 }
400 void ExpectPortalDetectorIsMock() {
401 EXPECT_EQ(portal_detector_, device_->portal_detector_.get());
402 }
403 scoped_refptr<MockConnection> connection_;
404 StrictMock<MockManager> manager_;
405 scoped_refptr<MockService> service_;
406
407 // Used only for EXPECT_CALL(). Object is owned by device.
408 MockPortalDetector *portal_detector_;
409};
410
Thieu Le85e050b2012-03-13 15:04:38 -0700411const int DevicePortalDetectionTest::kPortalAttempts = 2;
412
Paul Stewartd215af62012-04-24 23:25:50 -0700413TEST_F(DevicePortalDetectionTest, ServicePortalDetectionDisabled) {
414 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
415 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800416 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800417 .WillRepeatedly(Return(true));
Paul Stewartd215af62012-04-24 23:25:50 -0700418 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
419 EXPECT_FALSE(StartPortalDetection());
420}
421
422TEST_F(DevicePortalDetectionTest, TechnologyPortalDetectionDisabled) {
423 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
424 .WillOnce(Return(false));
425 EXPECT_CALL(*service_.get(), IsConnected())
426 .WillRepeatedly(Return(true));
427 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
428 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800429 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800430 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800431 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800432 EXPECT_FALSE(StartPortalDetection());
433}
434
Paul Stewartc681fa02012-03-02 19:40:04 -0800435TEST_F(DevicePortalDetectionTest, PortalDetectionProxyConfig) {
Paul Stewartd215af62012-04-24 23:25:50 -0700436 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
437 .WillOnce(Return(false));
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 Stewartc681fa02012-03-02 19:40:04 -0800440 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800441 .WillOnce(Return(true));
Paul Stewartd215af62012-04-24 23:25:50 -0700442 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
443 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800444 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800445 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800446 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800447 EXPECT_FALSE(StartPortalDetection());
448}
449
Paul Stewartc681fa02012-03-02 19:40:04 -0800450TEST_F(DevicePortalDetectionTest, PortalDetectionBadUrl) {
Paul Stewartd215af62012-04-24 23:25:50 -0700451 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
452 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800453 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800454 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800455 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800456 .WillOnce(Return(false));
Paul Stewartd215af62012-04-24 23:25:50 -0700457 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
458 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800459 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800460 .WillOnce(Return(true));
461 const string portal_url;
Paul Stewartc681fa02012-03-02 19:40:04 -0800462 EXPECT_CALL(manager_, GetPortalCheckURL())
Paul Stewart20088d82012-02-16 06:58:55 -0800463 .WillRepeatedly(ReturnRef(portal_url));
Paul Stewartc681fa02012-03-02 19:40:04 -0800464 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800465 EXPECT_FALSE(StartPortalDetection());
466}
467
Paul Stewartc681fa02012-03-02 19:40:04 -0800468TEST_F(DevicePortalDetectionTest, PortalDetectionStart) {
Paul Stewartd215af62012-04-24 23:25:50 -0700469 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
470 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800471 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800472 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800473 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800474 .WillOnce(Return(false));
Paul Stewartd215af62012-04-24 23:25:50 -0700475 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
476 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800477 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800478 .WillOnce(Return(true));
479 const string portal_url(PortalDetector::kDefaultURL);
Paul Stewartc681fa02012-03-02 19:40:04 -0800480 EXPECT_CALL(manager_, GetPortalCheckURL())
Paul Stewart20088d82012-02-16 06:58:55 -0800481 .WillRepeatedly(ReturnRef(portal_url));
Paul Stewartc681fa02012-03-02 19:40:04 -0800482 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline))
Paul Stewart20088d82012-02-16 06:58:55 -0800483 .Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800484 const string kInterfaceName("int0");
Paul Stewartc681fa02012-03-02 19:40:04 -0800485 EXPECT_CALL(*connection_.get(), interface_name())
486 .WillRepeatedly(ReturnRef(kInterfaceName));
Paul Stewart20088d82012-02-16 06:58:55 -0800487 const vector<string> kDNSServers;
Paul Stewartc681fa02012-03-02 19:40:04 -0800488 EXPECT_CALL(*connection_.get(), dns_servers())
489 .WillRepeatedly(ReturnRef(kDNSServers));
Paul Stewart20088d82012-02-16 06:58:55 -0800490 EXPECT_TRUE(StartPortalDetection());
491
492 // Drop all references to device_info before it falls out of scope.
493 SetConnection(NULL);
494 StopPortalDetection();
495}
496
Paul Stewartc681fa02012-03-02 19:40:04 -0800497TEST_F(DevicePortalDetectionTest, PortalDetectionNonFinal) {
498 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800499 .Times(0);
Paul Stewartc681fa02012-03-02 19:40:04 -0800500 EXPECT_CALL(*service_.get(), SetState(_))
Paul Stewart20088d82012-02-16 06:58:55 -0800501 .Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800502 PortalDetectorCallback(PortalDetector::Result(
503 PortalDetector::kPhaseUnknown,
504 PortalDetector::kStatusFailure,
Thieu Le85e050b2012-03-13 15:04:38 -0700505 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800506 false));
507}
508
Paul Stewartc681fa02012-03-02 19:40:04 -0800509TEST_F(DevicePortalDetectionTest, PortalDetectionFailure) {
510 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800511 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800512 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
Thieu Le85e050b2012-03-13 15:04:38 -0700513 EXPECT_CALL(metrics_,
514 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
515 Metrics::kPortalResultConnectionFailure,
516 Metrics::kPortalResultMax));
517 EXPECT_CALL(metrics_,
518 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
519 _, _, _, _)).Times(0);
520 EXPECT_CALL(metrics_,
521 SendToUMA("Network.Shill.Unknown.PortalAttempts",
522 kPortalAttempts,
523 Metrics::kMetricPortalAttemptsMin,
524 Metrics::kMetricPortalAttemptsMax,
525 Metrics::kMetricPortalAttemptsNumBuckets));
Paul Stewartc681fa02012-03-02 19:40:04 -0800526 EXPECT_CALL(*connection_.get(), is_default())
527 .WillOnce(Return(false));
Paul Stewart20088d82012-02-16 06:58:55 -0800528 PortalDetectorCallback(PortalDetector::Result(
Thieu Le85e050b2012-03-13 15:04:38 -0700529 PortalDetector::kPhaseConnection,
Paul Stewart20088d82012-02-16 06:58:55 -0800530 PortalDetector::kStatusFailure,
Thieu Le85e050b2012-03-13 15:04:38 -0700531 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800532 true));
533}
534
Paul Stewartc681fa02012-03-02 19:40:04 -0800535TEST_F(DevicePortalDetectionTest, PortalDetectionSuccess) {
536 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800537 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800538 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Thieu Le85e050b2012-03-13 15:04:38 -0700539 EXPECT_CALL(metrics_,
540 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
541 Metrics::kPortalResultSuccess,
542 Metrics::kPortalResultMax));
543 EXPECT_CALL(metrics_,
544 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
545 kPortalAttempts,
546 Metrics::kMetricPortalAttemptsToOnlineMin,
547 Metrics::kMetricPortalAttemptsToOnlineMax,
548 Metrics::kMetricPortalAttemptsToOnlineNumBuckets));
549 EXPECT_CALL(metrics_,
550 SendToUMA("Network.Shill.Unknown.PortalAttempts",
551 _, _, _, _)).Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800552 PortalDetectorCallback(PortalDetector::Result(
Thieu Le85e050b2012-03-13 15:04:38 -0700553 PortalDetector::kPhaseContent,
Paul Stewart20088d82012-02-16 06:58:55 -0800554 PortalDetector::kStatusSuccess,
Thieu Le85e050b2012-03-13 15:04:38 -0700555 kPortalAttempts,
556 true));
557}
558
559TEST_F(DevicePortalDetectionTest, PortalDetectionSuccessAfterFailure) {
560 EXPECT_CALL(*service_.get(), IsConnected())
561 .WillRepeatedly(Return(true));
562 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
563 EXPECT_CALL(metrics_,
564 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
565 Metrics::kPortalResultConnectionFailure,
566 Metrics::kPortalResultMax));
567 EXPECT_CALL(metrics_,
568 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
569 _, _, _, _)).Times(0);
570 EXPECT_CALL(metrics_,
571 SendToUMA("Network.Shill.Unknown.PortalAttempts",
572 kPortalAttempts,
573 Metrics::kMetricPortalAttemptsMin,
574 Metrics::kMetricPortalAttemptsMax,
575 Metrics::kMetricPortalAttemptsNumBuckets));
576 EXPECT_CALL(*connection_.get(), is_default())
577 .WillOnce(Return(false));
578 PortalDetectorCallback(PortalDetector::Result(
579 PortalDetector::kPhaseConnection,
580 PortalDetector::kStatusFailure,
581 kPortalAttempts,
582 true));
583 Mock::VerifyAndClearExpectations(&metrics_);
584
585 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
586 EXPECT_CALL(metrics_,
587 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
588 Metrics::kPortalResultSuccess,
589 Metrics::kPortalResultMax));
590 EXPECT_CALL(metrics_,
591 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
592 kPortalAttempts * 2,
593 Metrics::kMetricPortalAttemptsToOnlineMin,
594 Metrics::kMetricPortalAttemptsToOnlineMax,
595 Metrics::kMetricPortalAttemptsToOnlineNumBuckets));
596 EXPECT_CALL(metrics_,
597 SendToUMA("Network.Shill.Unknown.PortalAttempts",
598 _, _, _, _)).Times(0);
599 PortalDetectorCallback(PortalDetector::Result(
600 PortalDetector::kPhaseContent,
601 PortalDetector::kStatusSuccess,
602 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800603 true));
604}
605
Paul Stewartc681fa02012-03-02 19:40:04 -0800606TEST_F(DevicePortalDetectionTest, RequestPortalDetection) {
607 EXPECT_CALL(*service_.get(), state())
608 .WillOnce(Return(Service::kStateOnline))
609 .WillRepeatedly(Return(Service::kStatePortal));
610 EXPECT_FALSE(RequestPortalDetection());
611
612 EXPECT_CALL(*connection_.get(), is_default())
613 .WillOnce(Return(false))
614 .WillRepeatedly(Return(true));
615 EXPECT_FALSE(RequestPortalDetection());
616
617 EXPECT_CALL(*portal_detector_, IsInProgress())
618 .WillOnce(Return(true));
619 // Portal detection already running.
620 EXPECT_TRUE(RequestPortalDetection());
621
622 // Make sure our running mock portal detector was not replaced.
623 ExpectPortalDetectorIsMock();
624
625 // Throw away our pre-fabricated portal detector, and have the device create
626 // a new one.
627 StopPortalDetection();
Paul Stewartd215af62012-04-24 23:25:50 -0700628 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
629 .WillRepeatedly(Return(false));
630 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
631 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800632 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
633 .WillRepeatedly(Return(true));
634 EXPECT_CALL(*service_.get(), HasProxyConfig())
635 .WillRepeatedly(Return(false));
636 const string kPortalCheckURL("http://portal");
637 EXPECT_CALL(manager_, GetPortalCheckURL())
638 .WillOnce(ReturnRef(kPortalCheckURL));
639 const string kInterfaceName("int0");
640 EXPECT_CALL(*connection_.get(), interface_name())
641 .WillRepeatedly(ReturnRef(kInterfaceName));
642 const vector<string> kDNSServers;
643 EXPECT_CALL(*connection_.get(), dns_servers())
644 .WillRepeatedly(ReturnRef(kDNSServers));
645 EXPECT_TRUE(RequestPortalDetection());
646}
647
648TEST_F(DevicePortalDetectionTest, NotConnected) {
649 EXPECT_CALL(*service_.get(), IsConnected())
650 .WillOnce(Return(false));
651 SetServiceConnectedState(Service::kStatePortal);
652 // We don't check for the portal detector to be reset here, because
653 // it would have been reset as a part of disconnection.
654}
655
656TEST_F(DevicePortalDetectionTest, NotPortal) {
657 EXPECT_CALL(*service_.get(), IsConnected())
658 .WillOnce(Return(true));
659 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
660 SetServiceConnectedState(Service::kStateOnline);
661 ExpectPortalDetectorReset();
662}
663
664TEST_F(DevicePortalDetectionTest, NotDefault) {
665 EXPECT_CALL(*service_.get(), IsConnected())
666 .WillOnce(Return(true));
667 EXPECT_CALL(*connection_.get(), is_default())
668 .WillOnce(Return(false));
669 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
670 SetServiceConnectedState(Service::kStatePortal);
671 ExpectPortalDetectorReset();
672}
673
674TEST_F(DevicePortalDetectionTest, PortalIntervalIsZero) {
675 EXPECT_CALL(*service_.get(), IsConnected())
676 .WillOnce(Return(true));
677 EXPECT_CALL(*connection_.get(), is_default())
678 .WillOnce(Return(true));
679 EXPECT_CALL(manager_, GetPortalCheckInterval())
680 .WillOnce(Return(0));
681 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
682 SetServiceConnectedState(Service::kStatePortal);
683 ExpectPortalDetectorReset();
684}
685
686TEST_F(DevicePortalDetectionTest, RestartPortalDetection) {
687 EXPECT_CALL(*service_.get(), IsConnected())
688 .WillOnce(Return(true));
689 EXPECT_CALL(*connection_.get(), is_default())
690 .WillOnce(Return(true));
691 const int kPortalDetectionInterval = 10;
692 EXPECT_CALL(manager_, GetPortalCheckInterval())
693 .Times(AtLeast(1))
694 .WillRepeatedly(Return(kPortalDetectionInterval));
695 const string kPortalCheckURL("http://portal");
696 EXPECT_CALL(manager_, GetPortalCheckURL())
697 .WillOnce(ReturnRef(kPortalCheckURL));
698 EXPECT_CALL(*portal_detector_, StartAfterDelay(kPortalCheckURL,
699 kPortalDetectionInterval))
700 .WillOnce(Return(true));
701 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
702 SetServiceConnectedState(Service::kStatePortal);
703 ExpectPortalDetectorSet();
704}
705
Darin Petkovafa6fc42011-06-21 16:21:08 -0700706} // namespace shill