blob: 2f4dd172f5b7e3eee39c8a403f1c84c98a20cc65 [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"
Thieu Lefb46caf2012-03-08 11:57:15 -080033#include "shill/mock_routing_table.h"
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -070034#include "shill/mock_rtnl_handler.h"
Paul Stewart03dba0b2011-08-22 16:32:45 -070035#include "shill/mock_service.h"
Chris Masone5dec5f42011-07-22 14:07:55 -070036#include "shill/mock_store.h"
Paul Stewart20088d82012-02-16 06:58:55 -080037#include "shill/portal_detector.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070038#include "shill/property_store_unittest.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::_;
Chris Masone5dec5f42011-07-22 14:07:55 -070045using ::testing::AtLeast;
Thieu Le85e050b2012-03-13 15:04:38 -070046using ::testing::Mock;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070047using ::testing::NiceMock;
48using ::testing::Return;
Paul Stewart20088d82012-02-16 06:58:55 -080049using ::testing::ReturnRef;
Paul Stewart03dba0b2011-08-22 16:32:45 -070050using ::testing::StrictMock;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070051using ::testing::Test;
Chris Masone34af2182011-08-22 11:59:36 -070052using ::testing::Values;
Darin Petkovafa6fc42011-06-21 16:21:08 -070053
54namespace shill {
55
Chris Masone3bd3c8c2011-06-13 08:20:26 -070056class DeviceTest : public PropertyStoreTest {
Darin Petkovafa6fc42011-06-21 16:21:08 -070057 public:
58 DeviceTest()
Chris Masone2176a882011-09-14 22:29:15 -070059 : device_(new Device(control_interface(),
Paul Stewart20088d82012-02-16 06:58:55 -080060 dispatcher(),
Chris Masone626719f2011-08-18 16:58:48 -070061 NULL,
Paul Stewart20088d82012-02-16 06:58:55 -080062 manager(),
Chris Masone626719f2011-08-18 16:58:48 -070063 kDeviceName,
64 kDeviceAddress,
Thieu Lefb46caf2012-03-08 11:57:15 -080065 kDeviceInterfaceIndex,
Paul Stewartc681fa02012-03-02 19:40:04 -080066 Technology::kUnknown)),
67 device_info_(control_interface(), NULL, NULL, NULL) {
Chris Masone2176a882011-09-14 22:29:15 -070068 DHCPProvider::GetInstance()->glib_ = glib();
69 DHCPProvider::GetInstance()->control_interface_ = control_interface();
Darin Petkovafa6fc42011-06-21 16:21:08 -070070 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -070071 virtual ~DeviceTest() {}
Darin Petkovafa6fc42011-06-21 16:21:08 -070072
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -070073 virtual void SetUp() {
Thieu Le85e050b2012-03-13 15:04:38 -070074 device_->metrics_ = &metrics_;
Thieu Lefb46caf2012-03-08 11:57:15 -080075 device_->routing_table_ = &routing_table_;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -070076 device_->rtnl_handler_ = &rtnl_handler_;
77 }
78
Darin Petkovafa6fc42011-06-21 16:21:08 -070079 protected:
Chris Masone626719f2011-08-18 16:58:48 -070080 static const char kDeviceName[];
81 static const char kDeviceAddress[];
Thieu Lefb46caf2012-03-08 11:57:15 -080082 static const int kDeviceInterfaceIndex;
Chris Masone626719f2011-08-18 16:58:48 -070083
Darin Petkov79d74c92012-03-07 17:20:32 +010084 void OnIPConfigUpdated(const IPConfigRefPtr &ipconfig, bool success) {
85 device_->OnIPConfigUpdated(ipconfig, success);
Paul Stewart20088d82012-02-16 06:58:55 -080086 }
87
88 void SelectService(const ServiceRefPtr service) {
89 device_->SelectService(service);
90 }
91
Paul Stewart20088d82012-02-16 06:58:55 -080092 void SetConnection(ConnectionRefPtr connection) {
93 device_->connection_ = connection;
94 }
95
Darin Petkovafa6fc42011-06-21 16:21:08 -070096 MockControl control_interface_;
97 DeviceRefPtr device_;
Paul Stewartc681fa02012-03-02 19:40:04 -080098 MockDeviceInfo device_info_;
Thieu Le85e050b2012-03-13 15:04:38 -070099 MockMetrics metrics_;
Thieu Lefb46caf2012-03-08 11:57:15 -0800100 MockRoutingTable routing_table_;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700101 StrictMock<MockRTNLHandler> rtnl_handler_;
Darin Petkovafa6fc42011-06-21 16:21:08 -0700102};
103
Chris Masone626719f2011-08-18 16:58:48 -0700104const char DeviceTest::kDeviceName[] = "testdevice";
105const char DeviceTest::kDeviceAddress[] = "address";
Thieu Lefb46caf2012-03-08 11:57:15 -0800106const int DeviceTest::kDeviceInterfaceIndex = 0;
Chris Masone626719f2011-08-18 16:58:48 -0700107
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700108TEST_F(DeviceTest, Contains) {
mukesh agrawalde29fa82011-09-16 16:16:36 -0700109 EXPECT_TRUE(device_->store().Contains(flimflam::kNameProperty));
110 EXPECT_FALSE(device_->store().Contains(""));
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700111}
112
Chris Masonea8a2c252011-06-27 22:16:30 -0700113TEST_F(DeviceTest, GetProperties) {
114 map<string, ::DBus::Variant> props;
115 Error error(Error::kInvalidProperty, "");
116 {
117 ::DBus::Error dbus_error;
118 bool expected = true;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700119 device_->mutable_store()->SetBoolProperty(flimflam::kPoweredProperty,
120 expected,
121 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700122 DBusAdaptor::GetProperties(device_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700123 ASSERT_FALSE(props.find(flimflam::kPoweredProperty) == props.end());
124 EXPECT_EQ(props[flimflam::kPoweredProperty].reader().get_bool(),
125 expected);
126 }
127 {
128 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -0700129 DBusAdaptor::GetProperties(device_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700130 ASSERT_FALSE(props.find(flimflam::kNameProperty) == props.end());
131 EXPECT_EQ(props[flimflam::kNameProperty].reader().get_string(),
132 string(kDeviceName));
133 }
134}
135
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800136TEST_F(DeviceTest, SetProperty) {
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700137 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800138 EXPECT_TRUE(DBusAdaptor::SetProperty(device_->mutable_store(),
139 flimflam::kPoweredProperty,
140 PropertyStoreTest::kBoolV,
141 &error));
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700142
Chris Masoneb925cc82011-06-22 15:39:57 -0700143 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800144 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
145 flimflam::kAddressProperty,
146 PropertyStoreTest::kStringV,
147 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700148 EXPECT_EQ(invalid_args(), error.name());
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700149}
150
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800151TEST_F(DeviceTest, ClearProperty) {
152 ::DBus::Error error;
153 EXPECT_TRUE(device_->powered());
154
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800155 EXPECT_TRUE(DBusAdaptor::SetProperty(device_->mutable_store(),
156 flimflam::kPoweredProperty,
157 PropertyStoreTest::kBoolV,
158 &error));
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800159 EXPECT_FALSE(device_->powered());
160
161 EXPECT_TRUE(DBusAdaptor::ClearProperty(device_->mutable_store(),
162 flimflam::kPoweredProperty,
163 &error));
164 EXPECT_TRUE(device_->powered());
165}
166
167TEST_F(DeviceTest, ClearReadOnlyProperty) {
168 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800169 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
170 flimflam::kAddressProperty,
171 PropertyStoreTest::kStringV,
172 &error));
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800173}
174
175TEST_F(DeviceTest, ClearReadOnlyDerivedProperty) {
176 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800177 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
178 flimflam::kIPConfigsProperty,
179 PropertyStoreTest::kStringsV,
180 &error));
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800181}
182
Darin Petkovafa6fc42011-06-21 16:21:08 -0700183TEST_F(DeviceTest, TechnologyIs) {
Paul Stewartfdd16072011-09-16 12:41:35 -0700184 EXPECT_FALSE(device_->TechnologyIs(Technology::kEthernet));
Darin Petkovafa6fc42011-06-21 16:21:08 -0700185}
186
187TEST_F(DeviceTest, DestroyIPConfig) {
188 ASSERT_FALSE(device_->ipconfig_.get());
Chris Masone2176a882011-09-14 22:29:15 -0700189 device_->ipconfig_ = new IPConfig(control_interface(), kDeviceName);
Darin Petkovafa6fc42011-06-21 16:21:08 -0700190 device_->DestroyIPConfig();
191 ASSERT_FALSE(device_->ipconfig_.get());
192}
193
194TEST_F(DeviceTest, DestroyIPConfigNULL) {
195 ASSERT_FALSE(device_->ipconfig_.get());
196 device_->DestroyIPConfig();
197 ASSERT_FALSE(device_->ipconfig_.get());
198}
199
Paul Stewart2bf1d352011-12-06 15:02:55 -0800200TEST_F(DeviceTest, AcquireIPConfig) {
Chris Masone2176a882011-09-14 22:29:15 -0700201 device_->ipconfig_ = new IPConfig(control_interface(), "randomname");
202 EXPECT_CALL(*glib(), SpawnAsync(_, _, _, _, _, _, _, _))
Darin Petkovafa6fc42011-06-21 16:21:08 -0700203 .WillOnce(Return(false));
Paul Stewart2bf1d352011-12-06 15:02:55 -0800204 EXPECT_FALSE(device_->AcquireIPConfig());
Darin Petkovafa6fc42011-06-21 16:21:08 -0700205 ASSERT_TRUE(device_->ipconfig_.get());
206 EXPECT_EQ(kDeviceName, device_->ipconfig_->device_name());
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500207 EXPECT_FALSE(device_->ipconfig_->update_callback_.is_null());
Darin Petkovafa6fc42011-06-21 16:21:08 -0700208}
209
Chris Masone5dec5f42011-07-22 14:07:55 -0700210TEST_F(DeviceTest, Load) {
211 NiceMock<MockStore> storage;
212 const string id = device_->GetStorageIdentifier();
213 EXPECT_CALL(storage, ContainsGroup(id)).WillOnce(Return(true));
214 EXPECT_CALL(storage, GetBool(id, _, _))
215 .Times(AtLeast(1))
216 .WillRepeatedly(Return(true));
217 EXPECT_TRUE(device_->Load(&storage));
218}
219
220TEST_F(DeviceTest, Save) {
221 NiceMock<MockStore> storage;
222 const string id = device_->GetStorageIdentifier();
Chris Masone5dec5f42011-07-22 14:07:55 -0700223 EXPECT_CALL(storage, SetString(id, _, _))
224 .Times(AtLeast(1))
225 .WillRepeatedly(Return(true));
226 EXPECT_CALL(storage, SetBool(id, _, _))
227 .Times(AtLeast(1))
228 .WillRepeatedly(Return(true));
Chris Masone2176a882011-09-14 22:29:15 -0700229 scoped_refptr<MockIPConfig> ipconfig = new MockIPConfig(control_interface(),
Chris Masone34af2182011-08-22 11:59:36 -0700230 kDeviceName);
231 EXPECT_CALL(*ipconfig.get(), Save(_, _))
232 .WillOnce(Return(true));
233 device_->ipconfig_ = ipconfig;
Chris Masone5dec5f42011-07-22 14:07:55 -0700234 EXPECT_TRUE(device_->Save(&storage));
235}
236
Chris Masone34af2182011-08-22 11:59:36 -0700237TEST_F(DeviceTest, StorageIdGeneration) {
238 string to_process("/device/stuff/0");
239 ControlInterface::RpcIdToStorageId(&to_process);
240 EXPECT_TRUE(isalpha(to_process[0]));
241 EXPECT_EQ(string::npos, to_process.find('/'));
242}
243
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800244MATCHER(IsNullRefPtr, "") {
245 return !arg;
246}
247
248MATCHER(NotNullRefPtr, "") {
249 return arg;
250}
251
Paul Stewart03dba0b2011-08-22 16:32:45 -0700252TEST_F(DeviceTest, SelectedService) {
253 EXPECT_FALSE(device_->selected_service_.get());
254 device_->SetServiceState(Service::kStateAssociating);
255 scoped_refptr<MockService> service(
Chris Masone2176a882011-09-14 22:29:15 -0700256 new StrictMock<MockService>(control_interface(),
257 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800258 metrics(),
Chris Masone9d779932011-08-25 16:33:41 -0700259 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800260 SelectService(service);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700261 EXPECT_TRUE(device_->selected_service_.get() == service.get());
262
263 EXPECT_CALL(*service.get(), SetState(Service::kStateConfiguring));
264 device_->SetServiceState(Service::kStateConfiguring);
265 EXPECT_CALL(*service.get(), SetFailure(Service::kFailureOutOfRange));
266 device_->SetServiceFailure(Service::kFailureOutOfRange);
267
268 // Service should be returned to "Idle" state
269 EXPECT_CALL(*service.get(), state())
270 .WillOnce(Return(Service::kStateUnknown));
271 EXPECT_CALL(*service.get(), SetState(Service::kStateIdle));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800272 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Paul Stewart20088d82012-02-16 06:58:55 -0800273 SelectService(NULL);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700274
275 // A service in the "Failure" state should not be reset to "Idle"
Paul Stewart20088d82012-02-16 06:58:55 -0800276 SelectService(service);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700277 EXPECT_CALL(*service.get(), state())
278 .WillOnce(Return(Service::kStateFailure));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800279 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Paul Stewart20088d82012-02-16 06:58:55 -0800280 SelectService(NULL);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700281}
282
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800283TEST_F(DeviceTest, IPConfigUpdatedFailure) {
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 EXPECT_CALL(*service.get(), SetState(Service::kStateDisconnected));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800291 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Darin Petkov79d74c92012-03-07 17:20:32 +0100292 OnIPConfigUpdated(NULL, false);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800293}
294
295TEST_F(DeviceTest, IPConfigUpdatedSuccess) {
296 scoped_refptr<MockService> service(
297 new StrictMock<MockService>(control_interface(),
298 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800299 metrics(),
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800300 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800301 SelectService(service);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800302 scoped_refptr<MockIPConfig> ipconfig = new MockIPConfig(control_interface(),
303 kDeviceName);
304 EXPECT_CALL(*service.get(), SetState(Service::kStateConnected));
Paul Stewart20088d82012-02-16 06:58:55 -0800305 EXPECT_CALL(*service.get(), IsConnected())
306 .WillRepeatedly(Return(true));
307 EXPECT_CALL(*service.get(), SetState(Service::kStateOnline));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800308 EXPECT_CALL(*service.get(), SetConnection(NotNullRefPtr()));
Darin Petkov79d74c92012-03-07 17:20:32 +0100309 OnIPConfigUpdated(ipconfig.get(), true);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800310}
311
Thieu Lefb46caf2012-03-08 11:57:15 -0800312TEST_F(DeviceTest, Start) {
313 EXPECT_CALL(routing_table_, FlushRoutes(kDeviceInterfaceIndex));
314 device_->Start();
315}
316
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700317TEST_F(DeviceTest, Stop) {
318 device_->ipconfig_ = new IPConfig(&control_interface_, kDeviceName);
319 scoped_refptr<MockService> service(
320 new NiceMock<MockService>(&control_interface_,
321 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800322 metrics(),
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700323 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800324 SelectService(service);
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700325
326 EXPECT_CALL(*service.get(), state()).
327 WillRepeatedly(Return(Service::kStateConnected));
328 EXPECT_CALL(*dynamic_cast<DeviceMockAdaptor *>(device_->adaptor_.get()),
329 UpdateEnabled());
330 EXPECT_CALL(rtnl_handler_, SetInterfaceFlags(_, 0, IFF_UP));
331 device_->Stop();
332
333 EXPECT_FALSE(device_->ipconfig_.get());
334 EXPECT_FALSE(device_->selected_service_.get());
335}
336
Paul Stewartc681fa02012-03-02 19:40:04 -0800337
338class DevicePortalDetectionTest : public DeviceTest {
339 public:
340 DevicePortalDetectionTest()
341 : connection_(new StrictMock<MockConnection>(&device_info_)),
342 manager_(control_interface(),
343 dispatcher(),
344 metrics(),
345 glib()),
346 service_(new StrictMock<MockService>(control_interface(),
347 dispatcher(),
348 metrics(),
349 &manager_)),
350 portal_detector_(new StrictMock<MockPortalDetector>(connection_)) {}
351 virtual ~DevicePortalDetectionTest() {}
352 virtual void SetUp() {
353 DeviceTest::SetUp();
354 SelectService(service_);
355 SetConnection(connection_.get());
356 device_->portal_detector_.reset(portal_detector_); // Passes ownership.
357 device_->manager_ = &manager_;
358 }
359
360 protected:
Thieu Le85e050b2012-03-13 15:04:38 -0700361 static const int kPortalAttempts;
362
Paul Stewartc681fa02012-03-02 19:40:04 -0800363 bool StartPortalDetection() { return device_->StartPortalDetection(); }
364 void StopPortalDetection() { device_->StopPortalDetection(); }
365
366 void PortalDetectorCallback(const PortalDetector::Result &result) {
367 device_->PortalDetectorCallback(result);
368 }
369 bool RequestPortalDetection() {
370 return device_->RequestPortalDetection();
371 }
372 void SetServiceConnectedState(Service::ConnectState state) {
373 device_->SetServiceConnectedState(state);
374 }
375 void ExpectPortalDetectorReset() {
376 EXPECT_FALSE(device_->portal_detector_.get());
377 }
378 void ExpectPortalDetectorSet() {
379 EXPECT_TRUE(device_->portal_detector_.get());
380 }
381 void ExpectPortalDetectorIsMock() {
382 EXPECT_EQ(portal_detector_, device_->portal_detector_.get());
383 }
384 scoped_refptr<MockConnection> connection_;
385 StrictMock<MockManager> manager_;
386 scoped_refptr<MockService> service_;
387
388 // Used only for EXPECT_CALL(). Object is owned by device.
389 MockPortalDetector *portal_detector_;
390};
391
Thieu Le85e050b2012-03-13 15:04:38 -0700392const int DevicePortalDetectionTest::kPortalAttempts = 2;
393
Paul Stewartc681fa02012-03-02 19:40:04 -0800394TEST_F(DevicePortalDetectionTest, PortalDetectionDisabled) {
395 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800396 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800397 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800398 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800399 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800400 EXPECT_FALSE(StartPortalDetection());
401}
402
Paul Stewartc681fa02012-03-02 19:40:04 -0800403TEST_F(DevicePortalDetectionTest, PortalDetectionProxyConfig) {
404 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800405 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800406 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800407 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800408 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800409 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800410 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800411 EXPECT_FALSE(StartPortalDetection());
412}
413
Paul Stewartc681fa02012-03-02 19:40:04 -0800414TEST_F(DevicePortalDetectionTest, PortalDetectionBadUrl) {
415 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800416 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800417 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800418 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800419 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800420 .WillOnce(Return(true));
421 const string portal_url;
Paul Stewartc681fa02012-03-02 19:40:04 -0800422 EXPECT_CALL(manager_, GetPortalCheckURL())
Paul Stewart20088d82012-02-16 06:58:55 -0800423 .WillRepeatedly(ReturnRef(portal_url));
Paul Stewartc681fa02012-03-02 19:40:04 -0800424 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800425 EXPECT_FALSE(StartPortalDetection());
426}
427
Paul Stewartc681fa02012-03-02 19:40:04 -0800428TEST_F(DevicePortalDetectionTest, PortalDetectionStart) {
429 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800430 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800431 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800432 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800433 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800434 .WillOnce(Return(true));
435 const string portal_url(PortalDetector::kDefaultURL);
Paul Stewartc681fa02012-03-02 19:40:04 -0800436 EXPECT_CALL(manager_, GetPortalCheckURL())
Paul Stewart20088d82012-02-16 06:58:55 -0800437 .WillRepeatedly(ReturnRef(portal_url));
Paul Stewartc681fa02012-03-02 19:40:04 -0800438 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline))
Paul Stewart20088d82012-02-16 06:58:55 -0800439 .Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800440 const string kInterfaceName("int0");
Paul Stewartc681fa02012-03-02 19:40:04 -0800441 EXPECT_CALL(*connection_.get(), interface_name())
442 .WillRepeatedly(ReturnRef(kInterfaceName));
Paul Stewart20088d82012-02-16 06:58:55 -0800443 const vector<string> kDNSServers;
Paul Stewartc681fa02012-03-02 19:40:04 -0800444 EXPECT_CALL(*connection_.get(), dns_servers())
445 .WillRepeatedly(ReturnRef(kDNSServers));
Paul Stewart20088d82012-02-16 06:58:55 -0800446 EXPECT_TRUE(StartPortalDetection());
447
448 // Drop all references to device_info before it falls out of scope.
449 SetConnection(NULL);
450 StopPortalDetection();
451}
452
Paul Stewartc681fa02012-03-02 19:40:04 -0800453TEST_F(DevicePortalDetectionTest, PortalDetectionNonFinal) {
454 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800455 .Times(0);
Paul Stewartc681fa02012-03-02 19:40:04 -0800456 EXPECT_CALL(*service_.get(), SetState(_))
Paul Stewart20088d82012-02-16 06:58:55 -0800457 .Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800458 PortalDetectorCallback(PortalDetector::Result(
459 PortalDetector::kPhaseUnknown,
460 PortalDetector::kStatusFailure,
Thieu Le85e050b2012-03-13 15:04:38 -0700461 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800462 false));
463}
464
Paul Stewartc681fa02012-03-02 19:40:04 -0800465TEST_F(DevicePortalDetectionTest, PortalDetectionFailure) {
466 EXPECT_CALL(*service_.get(), IsConnected())
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::kStatePortal));
Thieu Le85e050b2012-03-13 15:04:38 -0700469 EXPECT_CALL(metrics_,
470 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
471 Metrics::kPortalResultConnectionFailure,
472 Metrics::kPortalResultMax));
473 EXPECT_CALL(metrics_,
474 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
475 _, _, _, _)).Times(0);
476 EXPECT_CALL(metrics_,
477 SendToUMA("Network.Shill.Unknown.PortalAttempts",
478 kPortalAttempts,
479 Metrics::kMetricPortalAttemptsMin,
480 Metrics::kMetricPortalAttemptsMax,
481 Metrics::kMetricPortalAttemptsNumBuckets));
Paul Stewartc681fa02012-03-02 19:40:04 -0800482 EXPECT_CALL(*connection_.get(), is_default())
483 .WillOnce(Return(false));
Paul Stewart20088d82012-02-16 06:58:55 -0800484 PortalDetectorCallback(PortalDetector::Result(
Thieu Le85e050b2012-03-13 15:04:38 -0700485 PortalDetector::kPhaseConnection,
Paul Stewart20088d82012-02-16 06:58:55 -0800486 PortalDetector::kStatusFailure,
Thieu Le85e050b2012-03-13 15:04:38 -0700487 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800488 true));
489}
490
Paul Stewartc681fa02012-03-02 19:40:04 -0800491TEST_F(DevicePortalDetectionTest, PortalDetectionSuccess) {
492 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800493 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800494 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Thieu Le85e050b2012-03-13 15:04:38 -0700495 EXPECT_CALL(metrics_,
496 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
497 Metrics::kPortalResultSuccess,
498 Metrics::kPortalResultMax));
499 EXPECT_CALL(metrics_,
500 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
501 kPortalAttempts,
502 Metrics::kMetricPortalAttemptsToOnlineMin,
503 Metrics::kMetricPortalAttemptsToOnlineMax,
504 Metrics::kMetricPortalAttemptsToOnlineNumBuckets));
505 EXPECT_CALL(metrics_,
506 SendToUMA("Network.Shill.Unknown.PortalAttempts",
507 _, _, _, _)).Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800508 PortalDetectorCallback(PortalDetector::Result(
Thieu Le85e050b2012-03-13 15:04:38 -0700509 PortalDetector::kPhaseContent,
Paul Stewart20088d82012-02-16 06:58:55 -0800510 PortalDetector::kStatusSuccess,
Thieu Le85e050b2012-03-13 15:04:38 -0700511 kPortalAttempts,
512 true));
513}
514
515TEST_F(DevicePortalDetectionTest, PortalDetectionSuccessAfterFailure) {
516 EXPECT_CALL(*service_.get(), IsConnected())
517 .WillRepeatedly(Return(true));
518 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
519 EXPECT_CALL(metrics_,
520 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
521 Metrics::kPortalResultConnectionFailure,
522 Metrics::kPortalResultMax));
523 EXPECT_CALL(metrics_,
524 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
525 _, _, _, _)).Times(0);
526 EXPECT_CALL(metrics_,
527 SendToUMA("Network.Shill.Unknown.PortalAttempts",
528 kPortalAttempts,
529 Metrics::kMetricPortalAttemptsMin,
530 Metrics::kMetricPortalAttemptsMax,
531 Metrics::kMetricPortalAttemptsNumBuckets));
532 EXPECT_CALL(*connection_.get(), is_default())
533 .WillOnce(Return(false));
534 PortalDetectorCallback(PortalDetector::Result(
535 PortalDetector::kPhaseConnection,
536 PortalDetector::kStatusFailure,
537 kPortalAttempts,
538 true));
539 Mock::VerifyAndClearExpectations(&metrics_);
540
541 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
542 EXPECT_CALL(metrics_,
543 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
544 Metrics::kPortalResultSuccess,
545 Metrics::kPortalResultMax));
546 EXPECT_CALL(metrics_,
547 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
548 kPortalAttempts * 2,
549 Metrics::kMetricPortalAttemptsToOnlineMin,
550 Metrics::kMetricPortalAttemptsToOnlineMax,
551 Metrics::kMetricPortalAttemptsToOnlineNumBuckets));
552 EXPECT_CALL(metrics_,
553 SendToUMA("Network.Shill.Unknown.PortalAttempts",
554 _, _, _, _)).Times(0);
555 PortalDetectorCallback(PortalDetector::Result(
556 PortalDetector::kPhaseContent,
557 PortalDetector::kStatusSuccess,
558 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800559 true));
560}
561
Paul Stewartc681fa02012-03-02 19:40:04 -0800562TEST_F(DevicePortalDetectionTest, RequestPortalDetection) {
563 EXPECT_CALL(*service_.get(), state())
564 .WillOnce(Return(Service::kStateOnline))
565 .WillRepeatedly(Return(Service::kStatePortal));
566 EXPECT_FALSE(RequestPortalDetection());
567
568 EXPECT_CALL(*connection_.get(), is_default())
569 .WillOnce(Return(false))
570 .WillRepeatedly(Return(true));
571 EXPECT_FALSE(RequestPortalDetection());
572
573 EXPECT_CALL(*portal_detector_, IsInProgress())
574 .WillOnce(Return(true));
575 // Portal detection already running.
576 EXPECT_TRUE(RequestPortalDetection());
577
578 // Make sure our running mock portal detector was not replaced.
579 ExpectPortalDetectorIsMock();
580
581 // Throw away our pre-fabricated portal detector, and have the device create
582 // a new one.
583 StopPortalDetection();
584 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
585 .WillRepeatedly(Return(true));
586 EXPECT_CALL(*service_.get(), HasProxyConfig())
587 .WillRepeatedly(Return(false));
588 const string kPortalCheckURL("http://portal");
589 EXPECT_CALL(manager_, GetPortalCheckURL())
590 .WillOnce(ReturnRef(kPortalCheckURL));
591 const string kInterfaceName("int0");
592 EXPECT_CALL(*connection_.get(), interface_name())
593 .WillRepeatedly(ReturnRef(kInterfaceName));
594 const vector<string> kDNSServers;
595 EXPECT_CALL(*connection_.get(), dns_servers())
596 .WillRepeatedly(ReturnRef(kDNSServers));
597 EXPECT_TRUE(RequestPortalDetection());
598}
599
600TEST_F(DevicePortalDetectionTest, NotConnected) {
601 EXPECT_CALL(*service_.get(), IsConnected())
602 .WillOnce(Return(false));
603 SetServiceConnectedState(Service::kStatePortal);
604 // We don't check for the portal detector to be reset here, because
605 // it would have been reset as a part of disconnection.
606}
607
608TEST_F(DevicePortalDetectionTest, NotPortal) {
609 EXPECT_CALL(*service_.get(), IsConnected())
610 .WillOnce(Return(true));
611 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
612 SetServiceConnectedState(Service::kStateOnline);
613 ExpectPortalDetectorReset();
614}
615
616TEST_F(DevicePortalDetectionTest, NotDefault) {
617 EXPECT_CALL(*service_.get(), IsConnected())
618 .WillOnce(Return(true));
619 EXPECT_CALL(*connection_.get(), is_default())
620 .WillOnce(Return(false));
621 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
622 SetServiceConnectedState(Service::kStatePortal);
623 ExpectPortalDetectorReset();
624}
625
626TEST_F(DevicePortalDetectionTest, PortalIntervalIsZero) {
627 EXPECT_CALL(*service_.get(), IsConnected())
628 .WillOnce(Return(true));
629 EXPECT_CALL(*connection_.get(), is_default())
630 .WillOnce(Return(true));
631 EXPECT_CALL(manager_, GetPortalCheckInterval())
632 .WillOnce(Return(0));
633 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
634 SetServiceConnectedState(Service::kStatePortal);
635 ExpectPortalDetectorReset();
636}
637
638TEST_F(DevicePortalDetectionTest, RestartPortalDetection) {
639 EXPECT_CALL(*service_.get(), IsConnected())
640 .WillOnce(Return(true));
641 EXPECT_CALL(*connection_.get(), is_default())
642 .WillOnce(Return(true));
643 const int kPortalDetectionInterval = 10;
644 EXPECT_CALL(manager_, GetPortalCheckInterval())
645 .Times(AtLeast(1))
646 .WillRepeatedly(Return(kPortalDetectionInterval));
647 const string kPortalCheckURL("http://portal");
648 EXPECT_CALL(manager_, GetPortalCheckURL())
649 .WillOnce(ReturnRef(kPortalCheckURL));
650 EXPECT_CALL(*portal_detector_, StartAfterDelay(kPortalCheckURL,
651 kPortalDetectionInterval))
652 .WillOnce(Return(true));
653 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
654 SetServiceConnectedState(Service::kStatePortal);
655 ExpectPortalDetectorSet();
656}
657
Darin Petkovafa6fc42011-06-21 16:21:08 -0700658} // namespace shill