blob: de7a1e6b0005611871dbf0922f4c842b84b69d04 [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
Eric Shienbrood9a245532012-03-07 14:20:39 -050056class TestDevice : public Device {
57 public:
58 TestDevice(ControlInterface *control_interface,
59 EventDispatcher *dispatcher,
60 Metrics *metrics,
61 Manager *manager,
62 const std::string &link_name,
63 const std::string &address,
64 int interface_index,
65 Technology::Identifier technology)
66 : Device(control_interface, dispatcher, metrics, manager, link_name,
67 address, interface_index, technology) {}
68 ~TestDevice() {}
69 virtual void Start(Error *error,
70 const EnabledStateChangedCallback &callback) {}
71 virtual void Stop(Error *error,
72 const EnabledStateChangedCallback &callback) {}
73};
74
Chris Masone3bd3c8c2011-06-13 08:20:26 -070075class DeviceTest : public PropertyStoreTest {
Darin Petkovafa6fc42011-06-21 16:21:08 -070076 public:
77 DeviceTest()
Eric Shienbrood9a245532012-03-07 14:20:39 -050078 : device_(new TestDevice(control_interface(),
79 dispatcher(),
80 NULL,
81 manager(),
82 kDeviceName,
83 kDeviceAddress,
84 kDeviceInterfaceIndex,
85 Technology::kUnknown)),
Paul Stewartc681fa02012-03-02 19:40:04 -080086 device_info_(control_interface(), NULL, NULL, NULL) {
Chris Masone2176a882011-09-14 22:29:15 -070087 DHCPProvider::GetInstance()->glib_ = glib();
88 DHCPProvider::GetInstance()->control_interface_ = control_interface();
Darin Petkovafa6fc42011-06-21 16:21:08 -070089 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -070090 virtual ~DeviceTest() {}
Darin Petkovafa6fc42011-06-21 16:21:08 -070091
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -070092 virtual void SetUp() {
Thieu Le85e050b2012-03-13 15:04:38 -070093 device_->metrics_ = &metrics_;
Thieu Lefb46caf2012-03-08 11:57:15 -080094 device_->routing_table_ = &routing_table_;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -070095 device_->rtnl_handler_ = &rtnl_handler_;
96 }
97
Darin Petkovafa6fc42011-06-21 16:21:08 -070098 protected:
Chris Masone626719f2011-08-18 16:58:48 -070099 static const char kDeviceName[];
100 static const char kDeviceAddress[];
Thieu Lefb46caf2012-03-08 11:57:15 -0800101 static const int kDeviceInterfaceIndex;
Chris Masone626719f2011-08-18 16:58:48 -0700102
Darin Petkov79d74c92012-03-07 17:20:32 +0100103 void OnIPConfigUpdated(const IPConfigRefPtr &ipconfig, bool success) {
104 device_->OnIPConfigUpdated(ipconfig, success);
Paul Stewart20088d82012-02-16 06:58:55 -0800105 }
106
107 void SelectService(const ServiceRefPtr service) {
108 device_->SelectService(service);
109 }
110
Paul Stewart20088d82012-02-16 06:58:55 -0800111 void SetConnection(ConnectionRefPtr connection) {
112 device_->connection_ = connection;
113 }
114
Darin Petkovafa6fc42011-06-21 16:21:08 -0700115 MockControl control_interface_;
116 DeviceRefPtr device_;
Paul Stewartc681fa02012-03-02 19:40:04 -0800117 MockDeviceInfo device_info_;
Thieu Le85e050b2012-03-13 15:04:38 -0700118 MockMetrics metrics_;
Thieu Lefb46caf2012-03-08 11:57:15 -0800119 MockRoutingTable routing_table_;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700120 StrictMock<MockRTNLHandler> rtnl_handler_;
Darin Petkovafa6fc42011-06-21 16:21:08 -0700121};
122
Chris Masone626719f2011-08-18 16:58:48 -0700123const char DeviceTest::kDeviceName[] = "testdevice";
124const char DeviceTest::kDeviceAddress[] = "address";
Thieu Lefb46caf2012-03-08 11:57:15 -0800125const int DeviceTest::kDeviceInterfaceIndex = 0;
Chris Masone626719f2011-08-18 16:58:48 -0700126
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700127TEST_F(DeviceTest, Contains) {
mukesh agrawalde29fa82011-09-16 16:16:36 -0700128 EXPECT_TRUE(device_->store().Contains(flimflam::kNameProperty));
129 EXPECT_FALSE(device_->store().Contains(""));
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700130}
131
Chris Masonea8a2c252011-06-27 22:16:30 -0700132TEST_F(DeviceTest, GetProperties) {
133 map<string, ::DBus::Variant> props;
134 Error error(Error::kInvalidProperty, "");
Eric Shienbrood9a245532012-03-07 14:20:39 -0500135 ::DBus::Error dbus_error;
136 DBusAdaptor::GetProperties(device_->store(), &props, &dbus_error);
137 ASSERT_FALSE(props.find(flimflam::kNameProperty) == props.end());
138 EXPECT_EQ(props[flimflam::kNameProperty].reader().get_string(),
139 string(kDeviceName));
Chris Masonea8a2c252011-06-27 22:16:30 -0700140}
141
Eric Shienbrood9a245532012-03-07 14:20:39 -0500142// Note: there are currently no writeable Device properties that
143// aren't registered in a subclass.
144TEST_F(DeviceTest, SetReadOnlyProperty) {
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700145 ::DBus::Error error;
Chris Masoneb925cc82011-06-22 15:39:57 -0700146 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800147 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
148 flimflam::kAddressProperty,
149 PropertyStoreTest::kStringV,
150 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700151 EXPECT_EQ(invalid_args(), error.name());
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700152}
153
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800154TEST_F(DeviceTest, ClearReadOnlyProperty) {
155 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800156 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
157 flimflam::kAddressProperty,
158 PropertyStoreTest::kStringV,
159 &error));
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800160}
161
162TEST_F(DeviceTest, ClearReadOnlyDerivedProperty) {
163 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800164 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
165 flimflam::kIPConfigsProperty,
166 PropertyStoreTest::kStringsV,
167 &error));
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800168}
169
Darin Petkovafa6fc42011-06-21 16:21:08 -0700170TEST_F(DeviceTest, TechnologyIs) {
Paul Stewartfdd16072011-09-16 12:41:35 -0700171 EXPECT_FALSE(device_->TechnologyIs(Technology::kEthernet));
Darin Petkovafa6fc42011-06-21 16:21:08 -0700172}
173
174TEST_F(DeviceTest, DestroyIPConfig) {
175 ASSERT_FALSE(device_->ipconfig_.get());
Chris Masone2176a882011-09-14 22:29:15 -0700176 device_->ipconfig_ = new IPConfig(control_interface(), kDeviceName);
Darin Petkovafa6fc42011-06-21 16:21:08 -0700177 device_->DestroyIPConfig();
178 ASSERT_FALSE(device_->ipconfig_.get());
179}
180
181TEST_F(DeviceTest, DestroyIPConfigNULL) {
182 ASSERT_FALSE(device_->ipconfig_.get());
183 device_->DestroyIPConfig();
184 ASSERT_FALSE(device_->ipconfig_.get());
185}
186
Paul Stewart2bf1d352011-12-06 15:02:55 -0800187TEST_F(DeviceTest, AcquireIPConfig) {
Chris Masone2176a882011-09-14 22:29:15 -0700188 device_->ipconfig_ = new IPConfig(control_interface(), "randomname");
189 EXPECT_CALL(*glib(), SpawnAsync(_, _, _, _, _, _, _, _))
Darin Petkovafa6fc42011-06-21 16:21:08 -0700190 .WillOnce(Return(false));
Paul Stewart2bf1d352011-12-06 15:02:55 -0800191 EXPECT_FALSE(device_->AcquireIPConfig());
Darin Petkovafa6fc42011-06-21 16:21:08 -0700192 ASSERT_TRUE(device_->ipconfig_.get());
193 EXPECT_EQ(kDeviceName, device_->ipconfig_->device_name());
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500194 EXPECT_FALSE(device_->ipconfig_->update_callback_.is_null());
Darin Petkovafa6fc42011-06-21 16:21:08 -0700195}
196
Chris Masone5dec5f42011-07-22 14:07:55 -0700197TEST_F(DeviceTest, Load) {
198 NiceMock<MockStore> storage;
199 const string id = device_->GetStorageIdentifier();
200 EXPECT_CALL(storage, ContainsGroup(id)).WillOnce(Return(true));
201 EXPECT_CALL(storage, GetBool(id, _, _))
202 .Times(AtLeast(1))
203 .WillRepeatedly(Return(true));
204 EXPECT_TRUE(device_->Load(&storage));
205}
206
207TEST_F(DeviceTest, Save) {
208 NiceMock<MockStore> storage;
209 const string id = device_->GetStorageIdentifier();
Chris Masone5dec5f42011-07-22 14:07:55 -0700210 EXPECT_CALL(storage, SetString(id, _, _))
211 .Times(AtLeast(1))
212 .WillRepeatedly(Return(true));
213 EXPECT_CALL(storage, SetBool(id, _, _))
214 .Times(AtLeast(1))
215 .WillRepeatedly(Return(true));
Chris Masone2176a882011-09-14 22:29:15 -0700216 scoped_refptr<MockIPConfig> ipconfig = new MockIPConfig(control_interface(),
Chris Masone34af2182011-08-22 11:59:36 -0700217 kDeviceName);
218 EXPECT_CALL(*ipconfig.get(), Save(_, _))
219 .WillOnce(Return(true));
220 device_->ipconfig_ = ipconfig;
Chris Masone5dec5f42011-07-22 14:07:55 -0700221 EXPECT_TRUE(device_->Save(&storage));
222}
223
Chris Masone34af2182011-08-22 11:59:36 -0700224TEST_F(DeviceTest, StorageIdGeneration) {
225 string to_process("/device/stuff/0");
226 ControlInterface::RpcIdToStorageId(&to_process);
227 EXPECT_TRUE(isalpha(to_process[0]));
228 EXPECT_EQ(string::npos, to_process.find('/'));
229}
230
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800231MATCHER(IsNullRefPtr, "") {
232 return !arg;
233}
234
235MATCHER(NotNullRefPtr, "") {
236 return arg;
237}
238
Paul Stewart03dba0b2011-08-22 16:32:45 -0700239TEST_F(DeviceTest, SelectedService) {
240 EXPECT_FALSE(device_->selected_service_.get());
241 device_->SetServiceState(Service::kStateAssociating);
242 scoped_refptr<MockService> service(
Chris Masone2176a882011-09-14 22:29:15 -0700243 new StrictMock<MockService>(control_interface(),
244 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800245 metrics(),
Chris Masone9d779932011-08-25 16:33:41 -0700246 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800247 SelectService(service);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700248 EXPECT_TRUE(device_->selected_service_.get() == service.get());
249
250 EXPECT_CALL(*service.get(), SetState(Service::kStateConfiguring));
251 device_->SetServiceState(Service::kStateConfiguring);
252 EXPECT_CALL(*service.get(), SetFailure(Service::kFailureOutOfRange));
253 device_->SetServiceFailure(Service::kFailureOutOfRange);
254
255 // Service should be returned to "Idle" state
256 EXPECT_CALL(*service.get(), state())
257 .WillOnce(Return(Service::kStateUnknown));
258 EXPECT_CALL(*service.get(), SetState(Service::kStateIdle));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800259 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Paul Stewart20088d82012-02-16 06:58:55 -0800260 SelectService(NULL);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700261
262 // A service in the "Failure" state should not be reset to "Idle"
Paul Stewart20088d82012-02-16 06:58:55 -0800263 SelectService(service);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700264 EXPECT_CALL(*service.get(), state())
265 .WillOnce(Return(Service::kStateFailure));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800266 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Paul Stewart20088d82012-02-16 06:58:55 -0800267 SelectService(NULL);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700268}
269
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800270TEST_F(DeviceTest, IPConfigUpdatedFailure) {
271 scoped_refptr<MockService> service(
272 new StrictMock<MockService>(control_interface(),
273 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800274 metrics(),
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800275 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800276 SelectService(service);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800277 EXPECT_CALL(*service.get(), SetState(Service::kStateDisconnected));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800278 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Darin Petkov79d74c92012-03-07 17:20:32 +0100279 OnIPConfigUpdated(NULL, false);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800280}
281
282TEST_F(DeviceTest, IPConfigUpdatedSuccess) {
283 scoped_refptr<MockService> service(
284 new StrictMock<MockService>(control_interface(),
285 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800286 metrics(),
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800287 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800288 SelectService(service);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800289 scoped_refptr<MockIPConfig> ipconfig = new MockIPConfig(control_interface(),
290 kDeviceName);
291 EXPECT_CALL(*service.get(), SetState(Service::kStateConnected));
Paul Stewart20088d82012-02-16 06:58:55 -0800292 EXPECT_CALL(*service.get(), IsConnected())
293 .WillRepeatedly(Return(true));
294 EXPECT_CALL(*service.get(), SetState(Service::kStateOnline));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800295 EXPECT_CALL(*service.get(), SetConnection(NotNullRefPtr()));
Darin Petkov79d74c92012-03-07 17:20:32 +0100296 OnIPConfigUpdated(ipconfig.get(), true);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800297}
298
Thieu Lefb46caf2012-03-08 11:57:15 -0800299TEST_F(DeviceTest, Start) {
300 EXPECT_CALL(routing_table_, FlushRoutes(kDeviceInterfaceIndex));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500301 device_->SetEnabled(true);
Thieu Lefb46caf2012-03-08 11:57:15 -0800302}
303
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700304TEST_F(DeviceTest, Stop) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500305 device_->enabled_ = true;
306 device_->enabled_pending_ = true;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700307 device_->ipconfig_ = new IPConfig(&control_interface_, kDeviceName);
308 scoped_refptr<MockService> service(
309 new NiceMock<MockService>(&control_interface_,
310 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800311 metrics(),
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700312 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800313 SelectService(service);
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700314
315 EXPECT_CALL(*service.get(), state()).
316 WillRepeatedly(Return(Service::kStateConnected));
317 EXPECT_CALL(*dynamic_cast<DeviceMockAdaptor *>(device_->adaptor_.get()),
318 UpdateEnabled());
Eric Shienbrood9a245532012-03-07 14:20:39 -0500319 EXPECT_CALL(*dynamic_cast<DeviceMockAdaptor *>(device_->adaptor_.get()),
320 EmitBoolChanged(flimflam::kPoweredProperty, false));
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700321 EXPECT_CALL(rtnl_handler_, SetInterfaceFlags(_, 0, IFF_UP));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500322 device_->SetEnabled(false);
323 device_->OnEnabledStateChanged(ResultCallback(), Error());
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700324
325 EXPECT_FALSE(device_->ipconfig_.get());
326 EXPECT_FALSE(device_->selected_service_.get());
327}
328
Paul Stewartc681fa02012-03-02 19:40:04 -0800329
330class DevicePortalDetectionTest : public DeviceTest {
331 public:
332 DevicePortalDetectionTest()
333 : connection_(new StrictMock<MockConnection>(&device_info_)),
334 manager_(control_interface(),
335 dispatcher(),
336 metrics(),
337 glib()),
338 service_(new StrictMock<MockService>(control_interface(),
339 dispatcher(),
340 metrics(),
341 &manager_)),
342 portal_detector_(new StrictMock<MockPortalDetector>(connection_)) {}
343 virtual ~DevicePortalDetectionTest() {}
344 virtual void SetUp() {
345 DeviceTest::SetUp();
346 SelectService(service_);
347 SetConnection(connection_.get());
348 device_->portal_detector_.reset(portal_detector_); // Passes ownership.
349 device_->manager_ = &manager_;
350 }
351
352 protected:
Thieu Le85e050b2012-03-13 15:04:38 -0700353 static const int kPortalAttempts;
354
Paul Stewartc681fa02012-03-02 19:40:04 -0800355 bool StartPortalDetection() { return device_->StartPortalDetection(); }
356 void StopPortalDetection() { device_->StopPortalDetection(); }
357
358 void PortalDetectorCallback(const PortalDetector::Result &result) {
359 device_->PortalDetectorCallback(result);
360 }
361 bool RequestPortalDetection() {
362 return device_->RequestPortalDetection();
363 }
364 void SetServiceConnectedState(Service::ConnectState state) {
365 device_->SetServiceConnectedState(state);
366 }
367 void ExpectPortalDetectorReset() {
368 EXPECT_FALSE(device_->portal_detector_.get());
369 }
370 void ExpectPortalDetectorSet() {
371 EXPECT_TRUE(device_->portal_detector_.get());
372 }
373 void ExpectPortalDetectorIsMock() {
374 EXPECT_EQ(portal_detector_, device_->portal_detector_.get());
375 }
376 scoped_refptr<MockConnection> connection_;
377 StrictMock<MockManager> manager_;
378 scoped_refptr<MockService> service_;
379
380 // Used only for EXPECT_CALL(). Object is owned by device.
381 MockPortalDetector *portal_detector_;
382};
383
Thieu Le85e050b2012-03-13 15:04:38 -0700384const int DevicePortalDetectionTest::kPortalAttempts = 2;
385
Paul Stewartc681fa02012-03-02 19:40:04 -0800386TEST_F(DevicePortalDetectionTest, PortalDetectionDisabled) {
387 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800388 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800389 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800390 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800391 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800392 EXPECT_FALSE(StartPortalDetection());
393}
394
Paul Stewartc681fa02012-03-02 19:40:04 -0800395TEST_F(DevicePortalDetectionTest, PortalDetectionProxyConfig) {
396 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800397 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800398 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800399 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800400 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800401 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800402 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800403 EXPECT_FALSE(StartPortalDetection());
404}
405
Paul Stewartc681fa02012-03-02 19:40:04 -0800406TEST_F(DevicePortalDetectionTest, PortalDetectionBadUrl) {
407 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800408 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800409 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800410 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800411 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800412 .WillOnce(Return(true));
413 const string portal_url;
Paul Stewartc681fa02012-03-02 19:40:04 -0800414 EXPECT_CALL(manager_, GetPortalCheckURL())
Paul Stewart20088d82012-02-16 06:58:55 -0800415 .WillRepeatedly(ReturnRef(portal_url));
Paul Stewartc681fa02012-03-02 19:40:04 -0800416 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800417 EXPECT_FALSE(StartPortalDetection());
418}
419
Paul Stewartc681fa02012-03-02 19:40:04 -0800420TEST_F(DevicePortalDetectionTest, PortalDetectionStart) {
421 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800422 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800423 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800424 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800425 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800426 .WillOnce(Return(true));
427 const string portal_url(PortalDetector::kDefaultURL);
Paul Stewartc681fa02012-03-02 19:40:04 -0800428 EXPECT_CALL(manager_, GetPortalCheckURL())
Paul Stewart20088d82012-02-16 06:58:55 -0800429 .WillRepeatedly(ReturnRef(portal_url));
Paul Stewartc681fa02012-03-02 19:40:04 -0800430 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline))
Paul Stewart20088d82012-02-16 06:58:55 -0800431 .Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800432 const string kInterfaceName("int0");
Paul Stewartc681fa02012-03-02 19:40:04 -0800433 EXPECT_CALL(*connection_.get(), interface_name())
434 .WillRepeatedly(ReturnRef(kInterfaceName));
Paul Stewart20088d82012-02-16 06:58:55 -0800435 const vector<string> kDNSServers;
Paul Stewartc681fa02012-03-02 19:40:04 -0800436 EXPECT_CALL(*connection_.get(), dns_servers())
437 .WillRepeatedly(ReturnRef(kDNSServers));
Paul Stewart20088d82012-02-16 06:58:55 -0800438 EXPECT_TRUE(StartPortalDetection());
439
440 // Drop all references to device_info before it falls out of scope.
441 SetConnection(NULL);
442 StopPortalDetection();
443}
444
Paul Stewartc681fa02012-03-02 19:40:04 -0800445TEST_F(DevicePortalDetectionTest, PortalDetectionNonFinal) {
446 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800447 .Times(0);
Paul Stewartc681fa02012-03-02 19:40:04 -0800448 EXPECT_CALL(*service_.get(), SetState(_))
Paul Stewart20088d82012-02-16 06:58:55 -0800449 .Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800450 PortalDetectorCallback(PortalDetector::Result(
451 PortalDetector::kPhaseUnknown,
452 PortalDetector::kStatusFailure,
Thieu Le85e050b2012-03-13 15:04:38 -0700453 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800454 false));
455}
456
Paul Stewartc681fa02012-03-02 19:40:04 -0800457TEST_F(DevicePortalDetectionTest, PortalDetectionFailure) {
458 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800459 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800460 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
Thieu Le85e050b2012-03-13 15:04:38 -0700461 EXPECT_CALL(metrics_,
462 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
463 Metrics::kPortalResultConnectionFailure,
464 Metrics::kPortalResultMax));
465 EXPECT_CALL(metrics_,
466 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
467 _, _, _, _)).Times(0);
468 EXPECT_CALL(metrics_,
469 SendToUMA("Network.Shill.Unknown.PortalAttempts",
470 kPortalAttempts,
471 Metrics::kMetricPortalAttemptsMin,
472 Metrics::kMetricPortalAttemptsMax,
473 Metrics::kMetricPortalAttemptsNumBuckets));
Paul Stewartc681fa02012-03-02 19:40:04 -0800474 EXPECT_CALL(*connection_.get(), is_default())
475 .WillOnce(Return(false));
Paul Stewart20088d82012-02-16 06:58:55 -0800476 PortalDetectorCallback(PortalDetector::Result(
Thieu Le85e050b2012-03-13 15:04:38 -0700477 PortalDetector::kPhaseConnection,
Paul Stewart20088d82012-02-16 06:58:55 -0800478 PortalDetector::kStatusFailure,
Thieu Le85e050b2012-03-13 15:04:38 -0700479 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800480 true));
481}
482
Paul Stewartc681fa02012-03-02 19:40:04 -0800483TEST_F(DevicePortalDetectionTest, PortalDetectionSuccess) {
484 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800485 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800486 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Thieu Le85e050b2012-03-13 15:04:38 -0700487 EXPECT_CALL(metrics_,
488 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
489 Metrics::kPortalResultSuccess,
490 Metrics::kPortalResultMax));
491 EXPECT_CALL(metrics_,
492 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
493 kPortalAttempts,
494 Metrics::kMetricPortalAttemptsToOnlineMin,
495 Metrics::kMetricPortalAttemptsToOnlineMax,
496 Metrics::kMetricPortalAttemptsToOnlineNumBuckets));
497 EXPECT_CALL(metrics_,
498 SendToUMA("Network.Shill.Unknown.PortalAttempts",
499 _, _, _, _)).Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800500 PortalDetectorCallback(PortalDetector::Result(
Thieu Le85e050b2012-03-13 15:04:38 -0700501 PortalDetector::kPhaseContent,
Paul Stewart20088d82012-02-16 06:58:55 -0800502 PortalDetector::kStatusSuccess,
Thieu Le85e050b2012-03-13 15:04:38 -0700503 kPortalAttempts,
504 true));
505}
506
507TEST_F(DevicePortalDetectionTest, PortalDetectionSuccessAfterFailure) {
508 EXPECT_CALL(*service_.get(), IsConnected())
509 .WillRepeatedly(Return(true));
510 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
511 EXPECT_CALL(metrics_,
512 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
513 Metrics::kPortalResultConnectionFailure,
514 Metrics::kPortalResultMax));
515 EXPECT_CALL(metrics_,
516 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
517 _, _, _, _)).Times(0);
518 EXPECT_CALL(metrics_,
519 SendToUMA("Network.Shill.Unknown.PortalAttempts",
520 kPortalAttempts,
521 Metrics::kMetricPortalAttemptsMin,
522 Metrics::kMetricPortalAttemptsMax,
523 Metrics::kMetricPortalAttemptsNumBuckets));
524 EXPECT_CALL(*connection_.get(), is_default())
525 .WillOnce(Return(false));
526 PortalDetectorCallback(PortalDetector::Result(
527 PortalDetector::kPhaseConnection,
528 PortalDetector::kStatusFailure,
529 kPortalAttempts,
530 true));
531 Mock::VerifyAndClearExpectations(&metrics_);
532
533 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
534 EXPECT_CALL(metrics_,
535 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
536 Metrics::kPortalResultSuccess,
537 Metrics::kPortalResultMax));
538 EXPECT_CALL(metrics_,
539 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
540 kPortalAttempts * 2,
541 Metrics::kMetricPortalAttemptsToOnlineMin,
542 Metrics::kMetricPortalAttemptsToOnlineMax,
543 Metrics::kMetricPortalAttemptsToOnlineNumBuckets));
544 EXPECT_CALL(metrics_,
545 SendToUMA("Network.Shill.Unknown.PortalAttempts",
546 _, _, _, _)).Times(0);
547 PortalDetectorCallback(PortalDetector::Result(
548 PortalDetector::kPhaseContent,
549 PortalDetector::kStatusSuccess,
550 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800551 true));
552}
553
Paul Stewartc681fa02012-03-02 19:40:04 -0800554TEST_F(DevicePortalDetectionTest, RequestPortalDetection) {
555 EXPECT_CALL(*service_.get(), state())
556 .WillOnce(Return(Service::kStateOnline))
557 .WillRepeatedly(Return(Service::kStatePortal));
558 EXPECT_FALSE(RequestPortalDetection());
559
560 EXPECT_CALL(*connection_.get(), is_default())
561 .WillOnce(Return(false))
562 .WillRepeatedly(Return(true));
563 EXPECT_FALSE(RequestPortalDetection());
564
565 EXPECT_CALL(*portal_detector_, IsInProgress())
566 .WillOnce(Return(true));
567 // Portal detection already running.
568 EXPECT_TRUE(RequestPortalDetection());
569
570 // Make sure our running mock portal detector was not replaced.
571 ExpectPortalDetectorIsMock();
572
573 // Throw away our pre-fabricated portal detector, and have the device create
574 // a new one.
575 StopPortalDetection();
576 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
577 .WillRepeatedly(Return(true));
578 EXPECT_CALL(*service_.get(), HasProxyConfig())
579 .WillRepeatedly(Return(false));
580 const string kPortalCheckURL("http://portal");
581 EXPECT_CALL(manager_, GetPortalCheckURL())
582 .WillOnce(ReturnRef(kPortalCheckURL));
583 const string kInterfaceName("int0");
584 EXPECT_CALL(*connection_.get(), interface_name())
585 .WillRepeatedly(ReturnRef(kInterfaceName));
586 const vector<string> kDNSServers;
587 EXPECT_CALL(*connection_.get(), dns_servers())
588 .WillRepeatedly(ReturnRef(kDNSServers));
589 EXPECT_TRUE(RequestPortalDetection());
590}
591
592TEST_F(DevicePortalDetectionTest, NotConnected) {
593 EXPECT_CALL(*service_.get(), IsConnected())
594 .WillOnce(Return(false));
595 SetServiceConnectedState(Service::kStatePortal);
596 // We don't check for the portal detector to be reset here, because
597 // it would have been reset as a part of disconnection.
598}
599
600TEST_F(DevicePortalDetectionTest, NotPortal) {
601 EXPECT_CALL(*service_.get(), IsConnected())
602 .WillOnce(Return(true));
603 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
604 SetServiceConnectedState(Service::kStateOnline);
605 ExpectPortalDetectorReset();
606}
607
608TEST_F(DevicePortalDetectionTest, NotDefault) {
609 EXPECT_CALL(*service_.get(), IsConnected())
610 .WillOnce(Return(true));
611 EXPECT_CALL(*connection_.get(), is_default())
612 .WillOnce(Return(false));
613 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
614 SetServiceConnectedState(Service::kStatePortal);
615 ExpectPortalDetectorReset();
616}
617
618TEST_F(DevicePortalDetectionTest, PortalIntervalIsZero) {
619 EXPECT_CALL(*service_.get(), IsConnected())
620 .WillOnce(Return(true));
621 EXPECT_CALL(*connection_.get(), is_default())
622 .WillOnce(Return(true));
623 EXPECT_CALL(manager_, GetPortalCheckInterval())
624 .WillOnce(Return(0));
625 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
626 SetServiceConnectedState(Service::kStatePortal);
627 ExpectPortalDetectorReset();
628}
629
630TEST_F(DevicePortalDetectionTest, RestartPortalDetection) {
631 EXPECT_CALL(*service_.get(), IsConnected())
632 .WillOnce(Return(true));
633 EXPECT_CALL(*connection_.get(), is_default())
634 .WillOnce(Return(true));
635 const int kPortalDetectionInterval = 10;
636 EXPECT_CALL(manager_, GetPortalCheckInterval())
637 .Times(AtLeast(1))
638 .WillRepeatedly(Return(kPortalDetectionInterval));
639 const string kPortalCheckURL("http://portal");
640 EXPECT_CALL(manager_, GetPortalCheckURL())
641 .WillOnce(ReturnRef(kPortalCheckURL));
642 EXPECT_CALL(*portal_detector_, StartAfterDelay(kPortalCheckURL,
643 kPortalDetectionInterval))
644 .WillOnce(Return(true));
645 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
646 SetServiceConnectedState(Service::kStatePortal);
647 ExpectPortalDetectorSet();
648}
649
Darin Petkovafa6fc42011-06-21 16:21:08 -0700650} // namespace shill