blob: 1e3610eb42c287ecf25aca5171e65c1bbdfe23d3 [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,
Jason Glasgow4a490792012-04-10 15:02:05 -040070 const EnabledStateChangedCallback &callback) {
71 DCHECK(error);
72 }
Eric Shienbrood9a245532012-03-07 14:20:39 -050073 virtual void Stop(Error *error,
Jason Glasgow4a490792012-04-10 15:02:05 -040074 const EnabledStateChangedCallback &callback) {
75 DCHECK(error);
76 }
Eric Shienbrood9a245532012-03-07 14:20:39 -050077};
78
Chris Masone3bd3c8c2011-06-13 08:20:26 -070079class DeviceTest : public PropertyStoreTest {
Darin Petkovafa6fc42011-06-21 16:21:08 -070080 public:
81 DeviceTest()
Eric Shienbrood9a245532012-03-07 14:20:39 -050082 : device_(new TestDevice(control_interface(),
83 dispatcher(),
84 NULL,
85 manager(),
86 kDeviceName,
87 kDeviceAddress,
88 kDeviceInterfaceIndex,
89 Technology::kUnknown)),
Paul Stewartc681fa02012-03-02 19:40:04 -080090 device_info_(control_interface(), NULL, NULL, NULL) {
Chris Masone2176a882011-09-14 22:29:15 -070091 DHCPProvider::GetInstance()->glib_ = glib();
92 DHCPProvider::GetInstance()->control_interface_ = control_interface();
Darin Petkovafa6fc42011-06-21 16:21:08 -070093 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -070094 virtual ~DeviceTest() {}
Darin Petkovafa6fc42011-06-21 16:21:08 -070095
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -070096 virtual void SetUp() {
Thieu Le85e050b2012-03-13 15:04:38 -070097 device_->metrics_ = &metrics_;
Thieu Lefb46caf2012-03-08 11:57:15 -080098 device_->routing_table_ = &routing_table_;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -070099 device_->rtnl_handler_ = &rtnl_handler_;
100 }
101
Darin Petkovafa6fc42011-06-21 16:21:08 -0700102 protected:
Chris Masone626719f2011-08-18 16:58:48 -0700103 static const char kDeviceName[];
104 static const char kDeviceAddress[];
Thieu Lefb46caf2012-03-08 11:57:15 -0800105 static const int kDeviceInterfaceIndex;
Chris Masone626719f2011-08-18 16:58:48 -0700106
Darin Petkov79d74c92012-03-07 17:20:32 +0100107 void OnIPConfigUpdated(const IPConfigRefPtr &ipconfig, bool success) {
108 device_->OnIPConfigUpdated(ipconfig, success);
Paul Stewart20088d82012-02-16 06:58:55 -0800109 }
110
111 void SelectService(const ServiceRefPtr service) {
112 device_->SelectService(service);
113 }
114
Paul Stewart20088d82012-02-16 06:58:55 -0800115 void SetConnection(ConnectionRefPtr connection) {
116 device_->connection_ = connection;
117 }
118
Darin Petkovafa6fc42011-06-21 16:21:08 -0700119 MockControl control_interface_;
120 DeviceRefPtr device_;
Paul Stewartc681fa02012-03-02 19:40:04 -0800121 MockDeviceInfo device_info_;
Thieu Le85e050b2012-03-13 15:04:38 -0700122 MockMetrics metrics_;
Thieu Lefb46caf2012-03-08 11:57:15 -0800123 MockRoutingTable routing_table_;
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
286TEST_F(DeviceTest, IPConfigUpdatedSuccess) {
287 scoped_refptr<MockService> service(
288 new StrictMock<MockService>(control_interface(),
289 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800290 metrics(),
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800291 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800292 SelectService(service);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800293 scoped_refptr<MockIPConfig> ipconfig = new MockIPConfig(control_interface(),
294 kDeviceName);
295 EXPECT_CALL(*service.get(), SetState(Service::kStateConnected));
Paul Stewart20088d82012-02-16 06:58:55 -0800296 EXPECT_CALL(*service.get(), IsConnected())
297 .WillRepeatedly(Return(true));
298 EXPECT_CALL(*service.get(), SetState(Service::kStateOnline));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800299 EXPECT_CALL(*service.get(), SetConnection(NotNullRefPtr()));
Darin Petkov79d74c92012-03-07 17:20:32 +0100300 OnIPConfigUpdated(ipconfig.get(), true);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800301}
302
Thieu Lefb46caf2012-03-08 11:57:15 -0800303TEST_F(DeviceTest, Start) {
304 EXPECT_CALL(routing_table_, FlushRoutes(kDeviceInterfaceIndex));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500305 device_->SetEnabled(true);
Thieu Lefb46caf2012-03-08 11:57:15 -0800306}
307
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700308TEST_F(DeviceTest, Stop) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500309 device_->enabled_ = true;
310 device_->enabled_pending_ = true;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700311 device_->ipconfig_ = new IPConfig(&control_interface_, kDeviceName);
312 scoped_refptr<MockService> service(
313 new NiceMock<MockService>(&control_interface_,
314 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800315 metrics(),
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700316 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800317 SelectService(service);
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700318
319 EXPECT_CALL(*service.get(), state()).
320 WillRepeatedly(Return(Service::kStateConnected));
321 EXPECT_CALL(*dynamic_cast<DeviceMockAdaptor *>(device_->adaptor_.get()),
322 UpdateEnabled());
Eric Shienbrood9a245532012-03-07 14:20:39 -0500323 EXPECT_CALL(*dynamic_cast<DeviceMockAdaptor *>(device_->adaptor_.get()),
324 EmitBoolChanged(flimflam::kPoweredProperty, false));
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700325 EXPECT_CALL(rtnl_handler_, SetInterfaceFlags(_, 0, IFF_UP));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500326 device_->SetEnabled(false);
327 device_->OnEnabledStateChanged(ResultCallback(), Error());
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700328
329 EXPECT_FALSE(device_->ipconfig_.get());
330 EXPECT_FALSE(device_->selected_service_.get());
331}
332
Paul Stewartc681fa02012-03-02 19:40:04 -0800333
334class DevicePortalDetectionTest : public DeviceTest {
335 public:
336 DevicePortalDetectionTest()
337 : connection_(new StrictMock<MockConnection>(&device_info_)),
338 manager_(control_interface(),
339 dispatcher(),
340 metrics(),
341 glib()),
342 service_(new StrictMock<MockService>(control_interface(),
343 dispatcher(),
344 metrics(),
345 &manager_)),
346 portal_detector_(new StrictMock<MockPortalDetector>(connection_)) {}
347 virtual ~DevicePortalDetectionTest() {}
348 virtual void SetUp() {
349 DeviceTest::SetUp();
350 SelectService(service_);
351 SetConnection(connection_.get());
352 device_->portal_detector_.reset(portal_detector_); // Passes ownership.
353 device_->manager_ = &manager_;
354 }
355
356 protected:
Thieu Le85e050b2012-03-13 15:04:38 -0700357 static const int kPortalAttempts;
358
Paul Stewartc681fa02012-03-02 19:40:04 -0800359 bool StartPortalDetection() { return device_->StartPortalDetection(); }
360 void StopPortalDetection() { device_->StopPortalDetection(); }
361
362 void PortalDetectorCallback(const PortalDetector::Result &result) {
363 device_->PortalDetectorCallback(result);
364 }
365 bool RequestPortalDetection() {
366 return device_->RequestPortalDetection();
367 }
368 void SetServiceConnectedState(Service::ConnectState state) {
369 device_->SetServiceConnectedState(state);
370 }
371 void ExpectPortalDetectorReset() {
372 EXPECT_FALSE(device_->portal_detector_.get());
373 }
374 void ExpectPortalDetectorSet() {
375 EXPECT_TRUE(device_->portal_detector_.get());
376 }
377 void ExpectPortalDetectorIsMock() {
378 EXPECT_EQ(portal_detector_, device_->portal_detector_.get());
379 }
380 scoped_refptr<MockConnection> connection_;
381 StrictMock<MockManager> manager_;
382 scoped_refptr<MockService> service_;
383
384 // Used only for EXPECT_CALL(). Object is owned by device.
385 MockPortalDetector *portal_detector_;
386};
387
Thieu Le85e050b2012-03-13 15:04:38 -0700388const int DevicePortalDetectionTest::kPortalAttempts = 2;
389
Paul Stewartc681fa02012-03-02 19:40:04 -0800390TEST_F(DevicePortalDetectionTest, PortalDetectionDisabled) {
391 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800392 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800393 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800394 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800395 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800396 EXPECT_FALSE(StartPortalDetection());
397}
398
Paul Stewartc681fa02012-03-02 19:40:04 -0800399TEST_F(DevicePortalDetectionTest, PortalDetectionProxyConfig) {
400 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800401 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800402 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800403 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800404 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800405 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800406 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800407 EXPECT_FALSE(StartPortalDetection());
408}
409
Paul Stewartc681fa02012-03-02 19:40:04 -0800410TEST_F(DevicePortalDetectionTest, PortalDetectionBadUrl) {
411 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800412 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800413 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800414 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800415 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800416 .WillOnce(Return(true));
417 const string portal_url;
Paul Stewartc681fa02012-03-02 19:40:04 -0800418 EXPECT_CALL(manager_, GetPortalCheckURL())
Paul Stewart20088d82012-02-16 06:58:55 -0800419 .WillRepeatedly(ReturnRef(portal_url));
Paul Stewartc681fa02012-03-02 19:40:04 -0800420 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800421 EXPECT_FALSE(StartPortalDetection());
422}
423
Paul Stewartc681fa02012-03-02 19:40:04 -0800424TEST_F(DevicePortalDetectionTest, PortalDetectionStart) {
425 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800426 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800427 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800428 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800429 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800430 .WillOnce(Return(true));
431 const string portal_url(PortalDetector::kDefaultURL);
Paul Stewartc681fa02012-03-02 19:40:04 -0800432 EXPECT_CALL(manager_, GetPortalCheckURL())
Paul Stewart20088d82012-02-16 06:58:55 -0800433 .WillRepeatedly(ReturnRef(portal_url));
Paul Stewartc681fa02012-03-02 19:40:04 -0800434 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline))
Paul Stewart20088d82012-02-16 06:58:55 -0800435 .Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800436 const string kInterfaceName("int0");
Paul Stewartc681fa02012-03-02 19:40:04 -0800437 EXPECT_CALL(*connection_.get(), interface_name())
438 .WillRepeatedly(ReturnRef(kInterfaceName));
Paul Stewart20088d82012-02-16 06:58:55 -0800439 const vector<string> kDNSServers;
Paul Stewartc681fa02012-03-02 19:40:04 -0800440 EXPECT_CALL(*connection_.get(), dns_servers())
441 .WillRepeatedly(ReturnRef(kDNSServers));
Paul Stewart20088d82012-02-16 06:58:55 -0800442 EXPECT_TRUE(StartPortalDetection());
443
444 // Drop all references to device_info before it falls out of scope.
445 SetConnection(NULL);
446 StopPortalDetection();
447}
448
Paul Stewartc681fa02012-03-02 19:40:04 -0800449TEST_F(DevicePortalDetectionTest, PortalDetectionNonFinal) {
450 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800451 .Times(0);
Paul Stewartc681fa02012-03-02 19:40:04 -0800452 EXPECT_CALL(*service_.get(), SetState(_))
Paul Stewart20088d82012-02-16 06:58:55 -0800453 .Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800454 PortalDetectorCallback(PortalDetector::Result(
455 PortalDetector::kPhaseUnknown,
456 PortalDetector::kStatusFailure,
Thieu Le85e050b2012-03-13 15:04:38 -0700457 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800458 false));
459}
460
Paul Stewartc681fa02012-03-02 19:40:04 -0800461TEST_F(DevicePortalDetectionTest, PortalDetectionFailure) {
462 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800463 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800464 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
Thieu Le85e050b2012-03-13 15:04:38 -0700465 EXPECT_CALL(metrics_,
466 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
467 Metrics::kPortalResultConnectionFailure,
468 Metrics::kPortalResultMax));
469 EXPECT_CALL(metrics_,
470 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
471 _, _, _, _)).Times(0);
472 EXPECT_CALL(metrics_,
473 SendToUMA("Network.Shill.Unknown.PortalAttempts",
474 kPortalAttempts,
475 Metrics::kMetricPortalAttemptsMin,
476 Metrics::kMetricPortalAttemptsMax,
477 Metrics::kMetricPortalAttemptsNumBuckets));
Paul Stewartc681fa02012-03-02 19:40:04 -0800478 EXPECT_CALL(*connection_.get(), is_default())
479 .WillOnce(Return(false));
Paul Stewart20088d82012-02-16 06:58:55 -0800480 PortalDetectorCallback(PortalDetector::Result(
Thieu Le85e050b2012-03-13 15:04:38 -0700481 PortalDetector::kPhaseConnection,
Paul Stewart20088d82012-02-16 06:58:55 -0800482 PortalDetector::kStatusFailure,
Thieu Le85e050b2012-03-13 15:04:38 -0700483 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800484 true));
485}
486
Paul Stewartc681fa02012-03-02 19:40:04 -0800487TEST_F(DevicePortalDetectionTest, PortalDetectionSuccess) {
488 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800489 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800490 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Thieu Le85e050b2012-03-13 15:04:38 -0700491 EXPECT_CALL(metrics_,
492 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
493 Metrics::kPortalResultSuccess,
494 Metrics::kPortalResultMax));
495 EXPECT_CALL(metrics_,
496 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
497 kPortalAttempts,
498 Metrics::kMetricPortalAttemptsToOnlineMin,
499 Metrics::kMetricPortalAttemptsToOnlineMax,
500 Metrics::kMetricPortalAttemptsToOnlineNumBuckets));
501 EXPECT_CALL(metrics_,
502 SendToUMA("Network.Shill.Unknown.PortalAttempts",
503 _, _, _, _)).Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800504 PortalDetectorCallback(PortalDetector::Result(
Thieu Le85e050b2012-03-13 15:04:38 -0700505 PortalDetector::kPhaseContent,
Paul Stewart20088d82012-02-16 06:58:55 -0800506 PortalDetector::kStatusSuccess,
Thieu Le85e050b2012-03-13 15:04:38 -0700507 kPortalAttempts,
508 true));
509}
510
511TEST_F(DevicePortalDetectionTest, PortalDetectionSuccessAfterFailure) {
512 EXPECT_CALL(*service_.get(), IsConnected())
513 .WillRepeatedly(Return(true));
514 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
515 EXPECT_CALL(metrics_,
516 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
517 Metrics::kPortalResultConnectionFailure,
518 Metrics::kPortalResultMax));
519 EXPECT_CALL(metrics_,
520 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
521 _, _, _, _)).Times(0);
522 EXPECT_CALL(metrics_,
523 SendToUMA("Network.Shill.Unknown.PortalAttempts",
524 kPortalAttempts,
525 Metrics::kMetricPortalAttemptsMin,
526 Metrics::kMetricPortalAttemptsMax,
527 Metrics::kMetricPortalAttemptsNumBuckets));
528 EXPECT_CALL(*connection_.get(), is_default())
529 .WillOnce(Return(false));
530 PortalDetectorCallback(PortalDetector::Result(
531 PortalDetector::kPhaseConnection,
532 PortalDetector::kStatusFailure,
533 kPortalAttempts,
534 true));
535 Mock::VerifyAndClearExpectations(&metrics_);
536
537 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
538 EXPECT_CALL(metrics_,
539 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
540 Metrics::kPortalResultSuccess,
541 Metrics::kPortalResultMax));
542 EXPECT_CALL(metrics_,
543 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
544 kPortalAttempts * 2,
545 Metrics::kMetricPortalAttemptsToOnlineMin,
546 Metrics::kMetricPortalAttemptsToOnlineMax,
547 Metrics::kMetricPortalAttemptsToOnlineNumBuckets));
548 EXPECT_CALL(metrics_,
549 SendToUMA("Network.Shill.Unknown.PortalAttempts",
550 _, _, _, _)).Times(0);
551 PortalDetectorCallback(PortalDetector::Result(
552 PortalDetector::kPhaseContent,
553 PortalDetector::kStatusSuccess,
554 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800555 true));
556}
557
Paul Stewartc681fa02012-03-02 19:40:04 -0800558TEST_F(DevicePortalDetectionTest, RequestPortalDetection) {
559 EXPECT_CALL(*service_.get(), state())
560 .WillOnce(Return(Service::kStateOnline))
561 .WillRepeatedly(Return(Service::kStatePortal));
562 EXPECT_FALSE(RequestPortalDetection());
563
564 EXPECT_CALL(*connection_.get(), is_default())
565 .WillOnce(Return(false))
566 .WillRepeatedly(Return(true));
567 EXPECT_FALSE(RequestPortalDetection());
568
569 EXPECT_CALL(*portal_detector_, IsInProgress())
570 .WillOnce(Return(true));
571 // Portal detection already running.
572 EXPECT_TRUE(RequestPortalDetection());
573
574 // Make sure our running mock portal detector was not replaced.
575 ExpectPortalDetectorIsMock();
576
577 // Throw away our pre-fabricated portal detector, and have the device create
578 // a new one.
579 StopPortalDetection();
580 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
581 .WillRepeatedly(Return(true));
582 EXPECT_CALL(*service_.get(), HasProxyConfig())
583 .WillRepeatedly(Return(false));
584 const string kPortalCheckURL("http://portal");
585 EXPECT_CALL(manager_, GetPortalCheckURL())
586 .WillOnce(ReturnRef(kPortalCheckURL));
587 const string kInterfaceName("int0");
588 EXPECT_CALL(*connection_.get(), interface_name())
589 .WillRepeatedly(ReturnRef(kInterfaceName));
590 const vector<string> kDNSServers;
591 EXPECT_CALL(*connection_.get(), dns_servers())
592 .WillRepeatedly(ReturnRef(kDNSServers));
593 EXPECT_TRUE(RequestPortalDetection());
594}
595
596TEST_F(DevicePortalDetectionTest, NotConnected) {
597 EXPECT_CALL(*service_.get(), IsConnected())
598 .WillOnce(Return(false));
599 SetServiceConnectedState(Service::kStatePortal);
600 // We don't check for the portal detector to be reset here, because
601 // it would have been reset as a part of disconnection.
602}
603
604TEST_F(DevicePortalDetectionTest, NotPortal) {
605 EXPECT_CALL(*service_.get(), IsConnected())
606 .WillOnce(Return(true));
607 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
608 SetServiceConnectedState(Service::kStateOnline);
609 ExpectPortalDetectorReset();
610}
611
612TEST_F(DevicePortalDetectionTest, NotDefault) {
613 EXPECT_CALL(*service_.get(), IsConnected())
614 .WillOnce(Return(true));
615 EXPECT_CALL(*connection_.get(), is_default())
616 .WillOnce(Return(false));
617 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
618 SetServiceConnectedState(Service::kStatePortal);
619 ExpectPortalDetectorReset();
620}
621
622TEST_F(DevicePortalDetectionTest, PortalIntervalIsZero) {
623 EXPECT_CALL(*service_.get(), IsConnected())
624 .WillOnce(Return(true));
625 EXPECT_CALL(*connection_.get(), is_default())
626 .WillOnce(Return(true));
627 EXPECT_CALL(manager_, GetPortalCheckInterval())
628 .WillOnce(Return(0));
629 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
630 SetServiceConnectedState(Service::kStatePortal);
631 ExpectPortalDetectorReset();
632}
633
634TEST_F(DevicePortalDetectionTest, RestartPortalDetection) {
635 EXPECT_CALL(*service_.get(), IsConnected())
636 .WillOnce(Return(true));
637 EXPECT_CALL(*connection_.get(), is_default())
638 .WillOnce(Return(true));
639 const int kPortalDetectionInterval = 10;
640 EXPECT_CALL(manager_, GetPortalCheckInterval())
641 .Times(AtLeast(1))
642 .WillRepeatedly(Return(kPortalDetectionInterval));
643 const string kPortalCheckURL("http://portal");
644 EXPECT_CALL(manager_, GetPortalCheckURL())
645 .WillOnce(ReturnRef(kPortalCheckURL));
646 EXPECT_CALL(*portal_detector_, StartAfterDelay(kPortalCheckURL,
647 kPortalDetectionInterval))
648 .WillOnce(Return(true));
649 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
650 SetServiceConnectedState(Service::kStatePortal);
651 ExpectPortalDetectorSet();
652}
653
Darin Petkovafa6fc42011-06-21 16:21:08 -0700654} // namespace shill