blob: 244c7ccfe2ffb9641688854e3f252c397e31ba18 [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"
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -070028#include "shill/mock_dhcp_config.h"
29#include "shill/mock_dhcp_provider.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070030#include "shill/mock_glib.h"
Chris Masone34af2182011-08-22 11:59:36 -070031#include "shill/mock_ipconfig.h"
Paul Stewart20088d82012-02-16 06:58:55 -080032#include "shill/mock_manager.h"
Thieu Le85e050b2012-03-13 15:04:38 -070033#include "shill/mock_metrics.h"
Paul Stewartc681fa02012-03-02 19:40:04 -080034#include "shill/mock_portal_detector.h"
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -070035#include "shill/mock_rtnl_handler.h"
Paul Stewart03dba0b2011-08-22 16:32:45 -070036#include "shill/mock_service.h"
Chris Masone5dec5f42011-07-22 14:07:55 -070037#include "shill/mock_store.h"
Paul Stewart20088d82012-02-16 06:58:55 -080038#include "shill/portal_detector.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070039#include "shill/property_store_unittest.h"
mukesh agrawalcc0fded2012-05-09 13:40:58 -070040#include "shill/static_ip_parameters.h"
Gaurav Shah435de2c2011-11-17 19:01:07 -080041#include "shill/technology.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070042
43using std::map;
44using std::string;
45using std::vector;
46using ::testing::_;
mukesh agrawalcc0fded2012-05-09 13:40:58 -070047using ::testing::AnyNumber;
Chris Masone5dec5f42011-07-22 14:07:55 -070048using ::testing::AtLeast;
Paul Stewart6ff27f52012-07-11 06:51:41 -070049using ::testing::Invoke;
Thieu Le85e050b2012-03-13 15:04:38 -070050using ::testing::Mock;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070051using ::testing::NiceMock;
52using ::testing::Return;
Paul Stewart20088d82012-02-16 06:58:55 -080053using ::testing::ReturnRef;
Paul Stewart03dba0b2011-08-22 16:32:45 -070054using ::testing::StrictMock;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070055using ::testing::Test;
Chris Masone34af2182011-08-22 11:59:36 -070056using ::testing::Values;
Darin Petkovafa6fc42011-06-21 16:21:08 -070057
58namespace shill {
59
Eric Shienbrood9a245532012-03-07 14:20:39 -050060class TestDevice : public Device {
61 public:
62 TestDevice(ControlInterface *control_interface,
63 EventDispatcher *dispatcher,
64 Metrics *metrics,
65 Manager *manager,
66 const std::string &link_name,
67 const std::string &address,
68 int interface_index,
69 Technology::Identifier technology)
70 : Device(control_interface, dispatcher, metrics, manager, link_name,
71 address, interface_index, technology) {}
72 ~TestDevice() {}
73 virtual void Start(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 virtual void Stop(Error *error,
Jason Glasgow4a490792012-04-10 15:02:05 -040078 const EnabledStateChangedCallback &callback) {
79 DCHECK(error);
80 }
Eric Shienbrood9a245532012-03-07 14:20:39 -050081};
82
Chris Masone3bd3c8c2011-06-13 08:20:26 -070083class DeviceTest : public PropertyStoreTest {
Darin Petkovafa6fc42011-06-21 16:21:08 -070084 public:
85 DeviceTest()
Eric Shienbrood9a245532012-03-07 14:20:39 -050086 : device_(new TestDevice(control_interface(),
87 dispatcher(),
88 NULL,
89 manager(),
90 kDeviceName,
91 kDeviceAddress,
92 kDeviceInterfaceIndex,
93 Technology::kUnknown)),
Paul Stewartc681fa02012-03-02 19:40:04 -080094 device_info_(control_interface(), NULL, NULL, NULL) {
Chris Masone2176a882011-09-14 22:29:15 -070095 DHCPProvider::GetInstance()->glib_ = glib();
96 DHCPProvider::GetInstance()->control_interface_ = control_interface();
mukesh agrawalcc0fded2012-05-09 13:40:58 -070097 DHCPProvider::GetInstance()->dispatcher_ = dispatcher();
Darin Petkovafa6fc42011-06-21 16:21:08 -070098 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -070099 virtual ~DeviceTest() {}
Darin Petkovafa6fc42011-06-21 16:21:08 -0700100
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700101 virtual void SetUp() {
Thieu Le85e050b2012-03-13 15:04:38 -0700102 device_->metrics_ = &metrics_;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700103 device_->rtnl_handler_ = &rtnl_handler_;
104 }
105
Darin Petkovafa6fc42011-06-21 16:21:08 -0700106 protected:
Chris Masone626719f2011-08-18 16:58:48 -0700107 static const char kDeviceName[];
108 static const char kDeviceAddress[];
Thieu Lefb46caf2012-03-08 11:57:15 -0800109 static const int kDeviceInterfaceIndex;
Chris Masone626719f2011-08-18 16:58:48 -0700110
Darin Petkov79d74c92012-03-07 17:20:32 +0100111 void OnIPConfigUpdated(const IPConfigRefPtr &ipconfig, bool success) {
112 device_->OnIPConfigUpdated(ipconfig, success);
Paul Stewart20088d82012-02-16 06:58:55 -0800113 }
114
115 void SelectService(const ServiceRefPtr service) {
116 device_->SelectService(service);
117 }
118
Paul Stewart20088d82012-02-16 06:58:55 -0800119 void SetConnection(ConnectionRefPtr connection) {
120 device_->connection_ = connection;
121 }
122
Darin Petkovafa6fc42011-06-21 16:21:08 -0700123 MockControl control_interface_;
124 DeviceRefPtr device_;
Paul Stewartc681fa02012-03-02 19:40:04 -0800125 MockDeviceInfo device_info_;
Thieu Le85e050b2012-03-13 15:04:38 -0700126 MockMetrics metrics_;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700127 StrictMock<MockRTNLHandler> rtnl_handler_;
Darin Petkovafa6fc42011-06-21 16:21:08 -0700128};
129
Chris Masone626719f2011-08-18 16:58:48 -0700130const char DeviceTest::kDeviceName[] = "testdevice";
131const char DeviceTest::kDeviceAddress[] = "address";
Thieu Lefb46caf2012-03-08 11:57:15 -0800132const int DeviceTest::kDeviceInterfaceIndex = 0;
Chris Masone626719f2011-08-18 16:58:48 -0700133
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700134TEST_F(DeviceTest, Contains) {
mukesh agrawalde29fa82011-09-16 16:16:36 -0700135 EXPECT_TRUE(device_->store().Contains(flimflam::kNameProperty));
136 EXPECT_FALSE(device_->store().Contains(""));
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700137}
138
Chris Masonea8a2c252011-06-27 22:16:30 -0700139TEST_F(DeviceTest, GetProperties) {
140 map<string, ::DBus::Variant> props;
141 Error error(Error::kInvalidProperty, "");
Eric Shienbrood9a245532012-03-07 14:20:39 -0500142 ::DBus::Error dbus_error;
143 DBusAdaptor::GetProperties(device_->store(), &props, &dbus_error);
144 ASSERT_FALSE(props.find(flimflam::kNameProperty) == props.end());
145 EXPECT_EQ(props[flimflam::kNameProperty].reader().get_string(),
146 string(kDeviceName));
Chris Masonea8a2c252011-06-27 22:16:30 -0700147}
148
Eric Shienbrood9a245532012-03-07 14:20:39 -0500149// Note: there are currently no writeable Device properties that
150// aren't registered in a subclass.
151TEST_F(DeviceTest, SetReadOnlyProperty) {
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700152 ::DBus::Error error;
Chris Masoneb925cc82011-06-22 15:39:57 -0700153 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800154 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
155 flimflam::kAddressProperty,
156 PropertyStoreTest::kStringV,
157 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700158 EXPECT_EQ(invalid_args(), error.name());
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700159}
160
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800161TEST_F(DeviceTest, ClearReadOnlyProperty) {
162 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800163 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
164 flimflam::kAddressProperty,
165 PropertyStoreTest::kStringV,
166 &error));
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800167}
168
169TEST_F(DeviceTest, ClearReadOnlyDerivedProperty) {
170 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800171 EXPECT_FALSE(DBusAdaptor::SetProperty(device_->mutable_store(),
172 flimflam::kIPConfigsProperty,
173 PropertyStoreTest::kStringsV,
174 &error));
mukesh agrawal8abd2f62012-01-30 14:56:14 -0800175}
176
Darin Petkovafa6fc42011-06-21 16:21:08 -0700177TEST_F(DeviceTest, DestroyIPConfig) {
178 ASSERT_FALSE(device_->ipconfig_.get());
Chris Masone2176a882011-09-14 22:29:15 -0700179 device_->ipconfig_ = new IPConfig(control_interface(), kDeviceName);
Darin Petkovafa6fc42011-06-21 16:21:08 -0700180 device_->DestroyIPConfig();
181 ASSERT_FALSE(device_->ipconfig_.get());
182}
183
184TEST_F(DeviceTest, DestroyIPConfigNULL) {
185 ASSERT_FALSE(device_->ipconfig_.get());
186 device_->DestroyIPConfig();
187 ASSERT_FALSE(device_->ipconfig_.get());
188}
189
Paul Stewart2bf1d352011-12-06 15:02:55 -0800190TEST_F(DeviceTest, AcquireIPConfig) {
Chris Masone2176a882011-09-14 22:29:15 -0700191 device_->ipconfig_ = new IPConfig(control_interface(), "randomname");
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -0700192 scoped_ptr<MockDHCPProvider> dhcp_provider(new MockDHCPProvider());
193 device_->dhcp_provider_ = dhcp_provider.get();
194 scoped_refptr<MockDHCPConfig> dhcp_config(new MockDHCPConfig(
195 control_interface(),
196 kDeviceName));
197 EXPECT_CALL(*dhcp_provider, CreateConfig(_, _, _, _))
198 .WillOnce(Return(dhcp_config));
199 EXPECT_CALL(*dhcp_config, RequestIP())
Darin Petkovafa6fc42011-06-21 16:21:08 -0700200 .WillOnce(Return(false));
Paul Stewart2bf1d352011-12-06 15:02:55 -0800201 EXPECT_FALSE(device_->AcquireIPConfig());
Darin Petkovafa6fc42011-06-21 16:21:08 -0700202 ASSERT_TRUE(device_->ipconfig_.get());
203 EXPECT_EQ(kDeviceName, device_->ipconfig_->device_name());
Eric Shienbrood3e20a232012-02-16 11:35:56 -0500204 EXPECT_FALSE(device_->ipconfig_->update_callback_.is_null());
Jorge Lucangeli Obesad43cc62012-04-11 16:25:43 -0700205 device_->dhcp_provider_ = NULL;
Darin Petkovafa6fc42011-06-21 16:21:08 -0700206}
207
Chris Masone5dec5f42011-07-22 14:07:55 -0700208TEST_F(DeviceTest, Load) {
209 NiceMock<MockStore> storage;
210 const string id = device_->GetStorageIdentifier();
211 EXPECT_CALL(storage, ContainsGroup(id)).WillOnce(Return(true));
Paul Stewart6ff27f52012-07-11 06:51:41 -0700212 EXPECT_CALL(storage, GetBool(id, Device::kStoragePowered, _))
213 .WillOnce(Return(true));
214 EXPECT_CALL(storage, GetUint64(id, Device::kStorageReceiveByteCount, _))
215 .WillOnce(Return(true));
216 EXPECT_CALL(storage, GetUint64(id, Device::kStorageTransmitByteCount, _))
217 .WillOnce(Return(true));
Chris Masone5dec5f42011-07-22 14:07:55 -0700218 EXPECT_TRUE(device_->Load(&storage));
219}
220
221TEST_F(DeviceTest, Save) {
222 NiceMock<MockStore> storage;
223 const string id = device_->GetStorageIdentifier();
Paul Stewart6ff27f52012-07-11 06:51:41 -0700224 EXPECT_CALL(storage, SetString(id, Device::kStorageIPConfigs, _))
225 .WillOnce(Return(true));
226 EXPECT_CALL(storage, SetBool(id, Device::kStoragePowered, _))
227 .WillOnce(Return(true));
Chris Masone2176a882011-09-14 22:29:15 -0700228 scoped_refptr<MockIPConfig> ipconfig = new MockIPConfig(control_interface(),
Chris Masone34af2182011-08-22 11:59:36 -0700229 kDeviceName);
230 EXPECT_CALL(*ipconfig.get(), Save(_, _))
231 .WillOnce(Return(true));
232 device_->ipconfig_ = ipconfig;
Paul Stewart6ff27f52012-07-11 06:51:41 -0700233 EXPECT_CALL(storage, SetUint64(id, Device::kStorageReceiveByteCount, _))
234 .WillOnce(Return(true));
235 EXPECT_CALL(storage, SetUint64(id, Device::kStorageTransmitByteCount, _))
236 .Times(AtLeast(true));
Chris Masone5dec5f42011-07-22 14:07:55 -0700237 EXPECT_TRUE(device_->Save(&storage));
238}
239
Chris Masone34af2182011-08-22 11:59:36 -0700240TEST_F(DeviceTest, StorageIdGeneration) {
241 string to_process("/device/stuff/0");
242 ControlInterface::RpcIdToStorageId(&to_process);
243 EXPECT_TRUE(isalpha(to_process[0]));
244 EXPECT_EQ(string::npos, to_process.find('/'));
245}
246
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800247MATCHER(IsNullRefPtr, "") {
248 return !arg;
249}
250
251MATCHER(NotNullRefPtr, "") {
252 return arg;
253}
254
Paul Stewart03dba0b2011-08-22 16:32:45 -0700255TEST_F(DeviceTest, SelectedService) {
256 EXPECT_FALSE(device_->selected_service_.get());
257 device_->SetServiceState(Service::kStateAssociating);
258 scoped_refptr<MockService> service(
Chris Masone2176a882011-09-14 22:29:15 -0700259 new StrictMock<MockService>(control_interface(),
260 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800261 metrics(),
Chris Masone9d779932011-08-25 16:33:41 -0700262 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800263 SelectService(service);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700264 EXPECT_TRUE(device_->selected_service_.get() == service.get());
265
266 EXPECT_CALL(*service.get(), SetState(Service::kStateConfiguring));
267 device_->SetServiceState(Service::kStateConfiguring);
268 EXPECT_CALL(*service.get(), SetFailure(Service::kFailureOutOfRange));
269 device_->SetServiceFailure(Service::kFailureOutOfRange);
270
271 // Service should be returned to "Idle" state
272 EXPECT_CALL(*service.get(), state())
273 .WillOnce(Return(Service::kStateUnknown));
274 EXPECT_CALL(*service.get(), SetState(Service::kStateIdle));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800275 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Paul Stewart20088d82012-02-16 06:58:55 -0800276 SelectService(NULL);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700277
278 // A service in the "Failure" state should not be reset to "Idle"
Paul Stewart20088d82012-02-16 06:58:55 -0800279 SelectService(service);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700280 EXPECT_CALL(*service.get(), state())
281 .WillOnce(Return(Service::kStateFailure));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800282 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Paul Stewart20088d82012-02-16 06:58:55 -0800283 SelectService(NULL);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700284}
285
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800286TEST_F(DeviceTest, IPConfigUpdatedFailure) {
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 EXPECT_CALL(*service.get(), SetState(Service::kStateDisconnected));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800294 EXPECT_CALL(*service.get(), SetConnection(IsNullRefPtr()));
Darin Petkov79d74c92012-03-07 17:20:32 +0100295 OnIPConfigUpdated(NULL, false);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800296}
297
mukesh agrawalcc0fded2012-05-09 13:40:58 -0700298TEST_F(DeviceTest, IPConfigUpdatedFailureWithStatic) {
299 scoped_refptr<MockService> service(
300 new StrictMock<MockService>(control_interface(),
301 dispatcher(),
302 metrics(),
303 manager()));
304 SelectService(service);
305 service->static_ip_parameters_.args_.SetString(
306 flimflam::kAddressProperty, "1.1.1.1");
307 service->static_ip_parameters_.args_.SetInt(flimflam::kPrefixlenProperty, 16);
308 EXPECT_CALL(*service.get(), SetState(_)).Times(0);
309 EXPECT_CALL(*service.get(), SetConnection(_)).Times(0);
310 OnIPConfigUpdated(NULL, false);
311}
312
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800313TEST_F(DeviceTest, IPConfigUpdatedSuccess) {
314 scoped_refptr<MockService> service(
315 new StrictMock<MockService>(control_interface(),
316 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800317 metrics(),
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800318 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800319 SelectService(service);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800320 scoped_refptr<MockIPConfig> ipconfig = new MockIPConfig(control_interface(),
321 kDeviceName);
322 EXPECT_CALL(*service.get(), SetState(Service::kStateConnected));
Paul Stewart20088d82012-02-16 06:58:55 -0800323 EXPECT_CALL(*service.get(), IsConnected())
324 .WillRepeatedly(Return(true));
Paul Stewartd215af62012-04-24 23:25:50 -0700325 EXPECT_CALL(*service.get(), IsPortalDetectionDisabled())
326 .WillRepeatedly(Return(true));
Paul Stewart20088d82012-02-16 06:58:55 -0800327 EXPECT_CALL(*service.get(), SetState(Service::kStateOnline));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800328 EXPECT_CALL(*service.get(), SetConnection(NotNullRefPtr()));
Darin Petkov79d74c92012-03-07 17:20:32 +0100329 OnIPConfigUpdated(ipconfig.get(), true);
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800330}
331
Darin Petkove7c6ad32012-06-29 10:22:09 +0200332TEST_F(DeviceTest, SetEnabledPersistent) {
333 EXPECT_FALSE(device_->enabled_);
334 EXPECT_FALSE(device_->enabled_pending_);
335 device_->enabled_persistent_ = false;
336 StrictMock<MockManager> manager(control_interface(),
337 dispatcher(),
338 metrics(),
339 glib());
340 EXPECT_CALL(manager, UpdateDevice(_));
341 device_->manager_ = &manager;
342 Error error;
343 device_->SetEnabledPersistent(true, &error, ResultCallback());
344 EXPECT_TRUE(device_->enabled_persistent_);
345 EXPECT_TRUE(device_->enabled_pending_);
346}
347
Thieu Lefb46caf2012-03-08 11:57:15 -0800348TEST_F(DeviceTest, Start) {
Paul Stewart8c116a92012-05-02 18:30:03 -0700349 EXPECT_FALSE(device_->running_);
350 EXPECT_FALSE(device_->enabled_);
351 EXPECT_FALSE(device_->enabled_pending_);
Eric Shienbrood9a245532012-03-07 14:20:39 -0500352 device_->SetEnabled(true);
Paul Stewart8c116a92012-05-02 18:30:03 -0700353 EXPECT_TRUE(device_->running_);
354 EXPECT_TRUE(device_->enabled_pending_);
Gary Morainbaeefdf2012-04-30 14:53:35 -0700355 device_->OnEnabledStateChanged(ResultCallback(),
356 Error(Error::kOperationFailed));
357 EXPECT_FALSE(device_->enabled_pending_);
Thieu Lefb46caf2012-03-08 11:57:15 -0800358}
359
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700360TEST_F(DeviceTest, Stop) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500361 device_->enabled_ = true;
362 device_->enabled_pending_ = true;
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700363 device_->ipconfig_ = new IPConfig(&control_interface_, kDeviceName);
364 scoped_refptr<MockService> service(
365 new NiceMock<MockService>(&control_interface_,
366 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -0800367 metrics(),
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700368 manager()));
Paul Stewart20088d82012-02-16 06:58:55 -0800369 SelectService(service);
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700370
371 EXPECT_CALL(*service.get(), state()).
372 WillRepeatedly(Return(Service::kStateConnected));
373 EXPECT_CALL(*dynamic_cast<DeviceMockAdaptor *>(device_->adaptor_.get()),
374 UpdateEnabled());
Eric Shienbrood9a245532012-03-07 14:20:39 -0500375 EXPECT_CALL(*dynamic_cast<DeviceMockAdaptor *>(device_->adaptor_.get()),
376 EmitBoolChanged(flimflam::kPoweredProperty, false));
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700377 EXPECT_CALL(rtnl_handler_, SetInterfaceFlags(_, 0, IFF_UP));
Eric Shienbrood9a245532012-03-07 14:20:39 -0500378 device_->SetEnabled(false);
379 device_->OnEnabledStateChanged(ResultCallback(), Error());
mukesh agrawal5c4dd0b2011-09-14 13:53:14 -0700380
381 EXPECT_FALSE(device_->ipconfig_.get());
382 EXPECT_FALSE(device_->selected_service_.get());
383}
384
Paul Stewartc681fa02012-03-02 19:40:04 -0800385class DevicePortalDetectionTest : public DeviceTest {
386 public:
387 DevicePortalDetectionTest()
388 : connection_(new StrictMock<MockConnection>(&device_info_)),
389 manager_(control_interface(),
390 dispatcher(),
391 metrics(),
392 glib()),
393 service_(new StrictMock<MockService>(control_interface(),
394 dispatcher(),
395 metrics(),
396 &manager_)),
397 portal_detector_(new StrictMock<MockPortalDetector>(connection_)) {}
398 virtual ~DevicePortalDetectionTest() {}
399 virtual void SetUp() {
400 DeviceTest::SetUp();
401 SelectService(service_);
402 SetConnection(connection_.get());
403 device_->portal_detector_.reset(portal_detector_); // Passes ownership.
404 device_->manager_ = &manager_;
405 }
406
407 protected:
Thieu Le85e050b2012-03-13 15:04:38 -0700408 static const int kPortalAttempts;
409
Paul Stewartc681fa02012-03-02 19:40:04 -0800410 bool StartPortalDetection() { return device_->StartPortalDetection(); }
411 void StopPortalDetection() { device_->StopPortalDetection(); }
412
413 void PortalDetectorCallback(const PortalDetector::Result &result) {
414 device_->PortalDetectorCallback(result);
415 }
416 bool RequestPortalDetection() {
417 return device_->RequestPortalDetection();
418 }
419 void SetServiceConnectedState(Service::ConnectState state) {
420 device_->SetServiceConnectedState(state);
421 }
422 void ExpectPortalDetectorReset() {
423 EXPECT_FALSE(device_->portal_detector_.get());
424 }
425 void ExpectPortalDetectorSet() {
426 EXPECT_TRUE(device_->portal_detector_.get());
427 }
428 void ExpectPortalDetectorIsMock() {
429 EXPECT_EQ(portal_detector_, device_->portal_detector_.get());
430 }
431 scoped_refptr<MockConnection> connection_;
432 StrictMock<MockManager> manager_;
433 scoped_refptr<MockService> service_;
434
435 // Used only for EXPECT_CALL(). Object is owned by device.
436 MockPortalDetector *portal_detector_;
437};
438
Thieu Le85e050b2012-03-13 15:04:38 -0700439const int DevicePortalDetectionTest::kPortalAttempts = 2;
440
Paul Stewartd215af62012-04-24 23:25:50 -0700441TEST_F(DevicePortalDetectionTest, ServicePortalDetectionDisabled) {
442 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
443 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800444 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800445 .WillRepeatedly(Return(true));
Paul Stewartd215af62012-04-24 23:25:50 -0700446 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
447 EXPECT_FALSE(StartPortalDetection());
448}
449
450TEST_F(DevicePortalDetectionTest, TechnologyPortalDetectionDisabled) {
451 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
452 .WillOnce(Return(false));
453 EXPECT_CALL(*service_.get(), IsConnected())
454 .WillRepeatedly(Return(true));
455 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
456 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800457 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800458 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800459 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800460 EXPECT_FALSE(StartPortalDetection());
461}
462
Paul Stewartc681fa02012-03-02 19:40:04 -0800463TEST_F(DevicePortalDetectionTest, PortalDetectionProxyConfig) {
Paul Stewartd215af62012-04-24 23:25:50 -0700464 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
465 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800466 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800467 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800468 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800469 .WillOnce(Return(true));
Paul Stewartd215af62012-04-24 23:25:50 -0700470 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
471 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800472 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800473 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800474 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800475 EXPECT_FALSE(StartPortalDetection());
476}
477
Paul Stewartc681fa02012-03-02 19:40:04 -0800478TEST_F(DevicePortalDetectionTest, PortalDetectionBadUrl) {
Paul Stewartd215af62012-04-24 23:25:50 -0700479 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
480 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800481 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800482 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800483 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800484 .WillOnce(Return(false));
Paul Stewartd215af62012-04-24 23:25:50 -0700485 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
486 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800487 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800488 .WillOnce(Return(true));
489 const string portal_url;
Paul Stewartc681fa02012-03-02 19:40:04 -0800490 EXPECT_CALL(manager_, GetPortalCheckURL())
Paul Stewart20088d82012-02-16 06:58:55 -0800491 .WillRepeatedly(ReturnRef(portal_url));
Paul Stewartc681fa02012-03-02 19:40:04 -0800492 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Paul Stewart20088d82012-02-16 06:58:55 -0800493 EXPECT_FALSE(StartPortalDetection());
494}
495
Paul Stewartc681fa02012-03-02 19:40:04 -0800496TEST_F(DevicePortalDetectionTest, PortalDetectionStart) {
Paul Stewartd215af62012-04-24 23:25:50 -0700497 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
498 .WillOnce(Return(false));
Paul Stewartc681fa02012-03-02 19:40:04 -0800499 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800500 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800501 EXPECT_CALL(*service_.get(), HasProxyConfig())
Paul Stewart20088d82012-02-16 06:58:55 -0800502 .WillOnce(Return(false));
Paul Stewartd215af62012-04-24 23:25:50 -0700503 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
504 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800505 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
Paul Stewart20088d82012-02-16 06:58:55 -0800506 .WillOnce(Return(true));
507 const string portal_url(PortalDetector::kDefaultURL);
Paul Stewartc681fa02012-03-02 19:40:04 -0800508 EXPECT_CALL(manager_, GetPortalCheckURL())
Paul Stewart20088d82012-02-16 06:58:55 -0800509 .WillRepeatedly(ReturnRef(portal_url));
Paul Stewartc681fa02012-03-02 19:40:04 -0800510 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline))
Paul Stewart20088d82012-02-16 06:58:55 -0800511 .Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800512 const string kInterfaceName("int0");
Paul Stewartc681fa02012-03-02 19:40:04 -0800513 EXPECT_CALL(*connection_.get(), interface_name())
514 .WillRepeatedly(ReturnRef(kInterfaceName));
Paul Stewart20088d82012-02-16 06:58:55 -0800515 const vector<string> kDNSServers;
Paul Stewartc681fa02012-03-02 19:40:04 -0800516 EXPECT_CALL(*connection_.get(), dns_servers())
517 .WillRepeatedly(ReturnRef(kDNSServers));
Paul Stewart20088d82012-02-16 06:58:55 -0800518 EXPECT_TRUE(StartPortalDetection());
519
520 // Drop all references to device_info before it falls out of scope.
521 SetConnection(NULL);
522 StopPortalDetection();
523}
524
Paul Stewartc681fa02012-03-02 19:40:04 -0800525TEST_F(DevicePortalDetectionTest, PortalDetectionNonFinal) {
526 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800527 .Times(0);
Paul Stewartc681fa02012-03-02 19:40:04 -0800528 EXPECT_CALL(*service_.get(), SetState(_))
Paul Stewart20088d82012-02-16 06:58:55 -0800529 .Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800530 PortalDetectorCallback(PortalDetector::Result(
531 PortalDetector::kPhaseUnknown,
532 PortalDetector::kStatusFailure,
Thieu Le85e050b2012-03-13 15:04:38 -0700533 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800534 false));
535}
536
Paul Stewartc681fa02012-03-02 19:40:04 -0800537TEST_F(DevicePortalDetectionTest, PortalDetectionFailure) {
538 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800539 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800540 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
Thieu Le85e050b2012-03-13 15:04:38 -0700541 EXPECT_CALL(metrics_,
542 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
543 Metrics::kPortalResultConnectionFailure,
544 Metrics::kPortalResultMax));
545 EXPECT_CALL(metrics_,
546 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
547 _, _, _, _)).Times(0);
548 EXPECT_CALL(metrics_,
549 SendToUMA("Network.Shill.Unknown.PortalAttempts",
550 kPortalAttempts,
551 Metrics::kMetricPortalAttemptsMin,
552 Metrics::kMetricPortalAttemptsMax,
553 Metrics::kMetricPortalAttemptsNumBuckets));
Paul Stewartc681fa02012-03-02 19:40:04 -0800554 EXPECT_CALL(*connection_.get(), is_default())
555 .WillOnce(Return(false));
Paul Stewart20088d82012-02-16 06:58:55 -0800556 PortalDetectorCallback(PortalDetector::Result(
Thieu Le85e050b2012-03-13 15:04:38 -0700557 PortalDetector::kPhaseConnection,
Paul Stewart20088d82012-02-16 06:58:55 -0800558 PortalDetector::kStatusFailure,
Thieu Le85e050b2012-03-13 15:04:38 -0700559 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800560 true));
561}
562
Paul Stewartc681fa02012-03-02 19:40:04 -0800563TEST_F(DevicePortalDetectionTest, PortalDetectionSuccess) {
564 EXPECT_CALL(*service_.get(), IsConnected())
Paul Stewart20088d82012-02-16 06:58:55 -0800565 .WillOnce(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800566 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
Thieu Le85e050b2012-03-13 15:04:38 -0700567 EXPECT_CALL(metrics_,
568 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
569 Metrics::kPortalResultSuccess,
570 Metrics::kPortalResultMax));
571 EXPECT_CALL(metrics_,
572 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
573 kPortalAttempts,
574 Metrics::kMetricPortalAttemptsToOnlineMin,
575 Metrics::kMetricPortalAttemptsToOnlineMax,
576 Metrics::kMetricPortalAttemptsToOnlineNumBuckets));
577 EXPECT_CALL(metrics_,
578 SendToUMA("Network.Shill.Unknown.PortalAttempts",
579 _, _, _, _)).Times(0);
Paul Stewart20088d82012-02-16 06:58:55 -0800580 PortalDetectorCallback(PortalDetector::Result(
Thieu Le85e050b2012-03-13 15:04:38 -0700581 PortalDetector::kPhaseContent,
Paul Stewart20088d82012-02-16 06:58:55 -0800582 PortalDetector::kStatusSuccess,
Thieu Le85e050b2012-03-13 15:04:38 -0700583 kPortalAttempts,
584 true));
585}
586
587TEST_F(DevicePortalDetectionTest, PortalDetectionSuccessAfterFailure) {
588 EXPECT_CALL(*service_.get(), IsConnected())
589 .WillRepeatedly(Return(true));
590 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
591 EXPECT_CALL(metrics_,
592 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
593 Metrics::kPortalResultConnectionFailure,
594 Metrics::kPortalResultMax));
595 EXPECT_CALL(metrics_,
596 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
597 _, _, _, _)).Times(0);
598 EXPECT_CALL(metrics_,
599 SendToUMA("Network.Shill.Unknown.PortalAttempts",
600 kPortalAttempts,
601 Metrics::kMetricPortalAttemptsMin,
602 Metrics::kMetricPortalAttemptsMax,
603 Metrics::kMetricPortalAttemptsNumBuckets));
604 EXPECT_CALL(*connection_.get(), is_default())
605 .WillOnce(Return(false));
606 PortalDetectorCallback(PortalDetector::Result(
607 PortalDetector::kPhaseConnection,
608 PortalDetector::kStatusFailure,
609 kPortalAttempts,
610 true));
611 Mock::VerifyAndClearExpectations(&metrics_);
612
613 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
614 EXPECT_CALL(metrics_,
615 SendEnumToUMA("Network.Shill.Unknown.PortalResult",
616 Metrics::kPortalResultSuccess,
617 Metrics::kPortalResultMax));
618 EXPECT_CALL(metrics_,
619 SendToUMA("Network.Shill.Unknown.PortalAttemptsToOnline",
620 kPortalAttempts * 2,
621 Metrics::kMetricPortalAttemptsToOnlineMin,
622 Metrics::kMetricPortalAttemptsToOnlineMax,
623 Metrics::kMetricPortalAttemptsToOnlineNumBuckets));
624 EXPECT_CALL(metrics_,
625 SendToUMA("Network.Shill.Unknown.PortalAttempts",
626 _, _, _, _)).Times(0);
627 PortalDetectorCallback(PortalDetector::Result(
628 PortalDetector::kPhaseContent,
629 PortalDetector::kStatusSuccess,
630 kPortalAttempts,
Paul Stewart20088d82012-02-16 06:58:55 -0800631 true));
632}
633
Paul Stewartc681fa02012-03-02 19:40:04 -0800634TEST_F(DevicePortalDetectionTest, RequestPortalDetection) {
635 EXPECT_CALL(*service_.get(), state())
636 .WillOnce(Return(Service::kStateOnline))
637 .WillRepeatedly(Return(Service::kStatePortal));
638 EXPECT_FALSE(RequestPortalDetection());
639
640 EXPECT_CALL(*connection_.get(), is_default())
641 .WillOnce(Return(false))
642 .WillRepeatedly(Return(true));
643 EXPECT_FALSE(RequestPortalDetection());
644
645 EXPECT_CALL(*portal_detector_, IsInProgress())
646 .WillOnce(Return(true));
647 // Portal detection already running.
648 EXPECT_TRUE(RequestPortalDetection());
649
650 // Make sure our running mock portal detector was not replaced.
651 ExpectPortalDetectorIsMock();
652
653 // Throw away our pre-fabricated portal detector, and have the device create
654 // a new one.
655 StopPortalDetection();
Paul Stewartd215af62012-04-24 23:25:50 -0700656 EXPECT_CALL(*service_.get(), IsPortalDetectionDisabled())
657 .WillRepeatedly(Return(false));
658 EXPECT_CALL(*service_.get(), IsPortalDetectionAuto())
659 .WillRepeatedly(Return(true));
Paul Stewartc681fa02012-03-02 19:40:04 -0800660 EXPECT_CALL(manager_, IsPortalDetectionEnabled(device_->technology()))
661 .WillRepeatedly(Return(true));
662 EXPECT_CALL(*service_.get(), HasProxyConfig())
663 .WillRepeatedly(Return(false));
664 const string kPortalCheckURL("http://portal");
665 EXPECT_CALL(manager_, GetPortalCheckURL())
666 .WillOnce(ReturnRef(kPortalCheckURL));
667 const string kInterfaceName("int0");
668 EXPECT_CALL(*connection_.get(), interface_name())
669 .WillRepeatedly(ReturnRef(kInterfaceName));
670 const vector<string> kDNSServers;
671 EXPECT_CALL(*connection_.get(), dns_servers())
672 .WillRepeatedly(ReturnRef(kDNSServers));
673 EXPECT_TRUE(RequestPortalDetection());
674}
675
676TEST_F(DevicePortalDetectionTest, NotConnected) {
677 EXPECT_CALL(*service_.get(), IsConnected())
678 .WillOnce(Return(false));
679 SetServiceConnectedState(Service::kStatePortal);
680 // We don't check for the portal detector to be reset here, because
681 // it would have been reset as a part of disconnection.
682}
683
684TEST_F(DevicePortalDetectionTest, NotPortal) {
685 EXPECT_CALL(*service_.get(), IsConnected())
686 .WillOnce(Return(true));
687 EXPECT_CALL(*service_.get(), SetState(Service::kStateOnline));
688 SetServiceConnectedState(Service::kStateOnline);
689 ExpectPortalDetectorReset();
690}
691
692TEST_F(DevicePortalDetectionTest, NotDefault) {
693 EXPECT_CALL(*service_.get(), IsConnected())
694 .WillOnce(Return(true));
695 EXPECT_CALL(*connection_.get(), is_default())
696 .WillOnce(Return(false));
697 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
698 SetServiceConnectedState(Service::kStatePortal);
699 ExpectPortalDetectorReset();
700}
701
702TEST_F(DevicePortalDetectionTest, PortalIntervalIsZero) {
703 EXPECT_CALL(*service_.get(), IsConnected())
704 .WillOnce(Return(true));
705 EXPECT_CALL(*connection_.get(), is_default())
706 .WillOnce(Return(true));
707 EXPECT_CALL(manager_, GetPortalCheckInterval())
708 .WillOnce(Return(0));
709 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
710 SetServiceConnectedState(Service::kStatePortal);
711 ExpectPortalDetectorReset();
712}
713
714TEST_F(DevicePortalDetectionTest, RestartPortalDetection) {
715 EXPECT_CALL(*service_.get(), IsConnected())
716 .WillOnce(Return(true));
717 EXPECT_CALL(*connection_.get(), is_default())
718 .WillOnce(Return(true));
719 const int kPortalDetectionInterval = 10;
720 EXPECT_CALL(manager_, GetPortalCheckInterval())
721 .Times(AtLeast(1))
722 .WillRepeatedly(Return(kPortalDetectionInterval));
723 const string kPortalCheckURL("http://portal");
724 EXPECT_CALL(manager_, GetPortalCheckURL())
725 .WillOnce(ReturnRef(kPortalCheckURL));
726 EXPECT_CALL(*portal_detector_, StartAfterDelay(kPortalCheckURL,
727 kPortalDetectionInterval))
728 .WillOnce(Return(true));
729 EXPECT_CALL(*service_.get(), SetState(Service::kStatePortal));
730 SetServiceConnectedState(Service::kStatePortal);
731 ExpectPortalDetectorSet();
732}
733
Paul Stewart6ff27f52012-07-11 06:51:41 -0700734class DeviceByteCountTest : public DeviceTest {
735 public:
736 DeviceByteCountTest()
737 : manager_(control_interface(),
738 dispatcher(),
739 metrics(),
740 glib()),
741 rx_byte_count_(0),
742 tx_byte_count_(0),
743 rx_stored_byte_count_(0),
744 tx_stored_byte_count_(0) {}
745 virtual ~DeviceByteCountTest() {}
746
747 virtual void SetUp() {
748 DeviceTest::SetUp();
749 EXPECT_CALL(manager_, device_info()).WillRepeatedly(Return(&device_info_));
750 EXPECT_CALL(device_info_, GetByteCounts(kDeviceInterfaceIndex, _, _))
751 .WillRepeatedly(Invoke(this, &DeviceByteCountTest::ReturnByteCounts));
752 const string id = device_->GetStorageIdentifier();
753 EXPECT_CALL(storage_, ContainsGroup(id)).WillRepeatedly(Return(true));
754 EXPECT_CALL(storage_, GetUint64(id, Device::kStorageReceiveByteCount, _))
755 .WillRepeatedly(
756 Invoke(this, &DeviceByteCountTest::GetStoredReceiveCount));
757 EXPECT_CALL(storage_, GetUint64(id, Device::kStorageTransmitByteCount, _))
758 .WillRepeatedly(
759 Invoke(this, &DeviceByteCountTest::GetStoredTransmitCount));
760 }
761
762 bool ReturnByteCounts(int interface_index, uint64 *rx, uint64 *tx) {
763 *rx = rx_byte_count_;
764 *tx = tx_byte_count_;
765 return true;
766 }
767
768 bool ExpectByteCounts(DeviceRefPtr device,
769 int64 expected_rx, int64 expected_tx) {
770 int64 actual_rx = device->GetReceiveByteCount(NULL);
771 int64 actual_tx = device->GetTransmitByteCount(NULL);
772 EXPECT_EQ(expected_rx, actual_rx);
773 EXPECT_EQ(expected_tx, actual_tx);
774 return expected_rx == actual_rx && expected_tx == actual_tx;
775 }
776
777 void ExpectSavedCounts(DeviceRefPtr device,
778 int64 expected_rx, int64 expected_tx) {
779 EXPECT_CALL(storage_,
780 SetUint64(_, Device::kStorageReceiveByteCount, expected_rx))
781 .WillOnce(Return(true));
782 EXPECT_CALL(storage_,
783 SetUint64(_, Device::kStorageTransmitByteCount, expected_tx))
784 .WillOnce(Return(true));
785 EXPECT_TRUE(device->Save(&storage_));
786 }
787
788
789 bool GetStoredReceiveCount(const string &group, const string &key,
790 uint64 *value) {
791 if (!rx_stored_byte_count_) {
792 return false;
793 }
794 *value = rx_stored_byte_count_;
795 return true;
796 }
797
798 bool GetStoredTransmitCount(const string &group, const string &key,
799 uint64 *value) {
800 if (!tx_stored_byte_count_) {
801 return false;
802 }
803 *value = tx_stored_byte_count_;
804 return true;
805 }
806
807 protected:
808 NiceMock<MockManager> manager_;
809 NiceMock<MockStore> storage_;
810 uint64 rx_byte_count_;
811 uint64 tx_byte_count_;
812 uint64 rx_stored_byte_count_;
813 uint64 tx_stored_byte_count_;
814};
815
816
817TEST_F(DeviceByteCountTest, GetByteCounts) {
818 // On Device initialization, byte counts should be zero, independent of
819 // the byte counts reported by the interface.
820 rx_byte_count_ = 123;
821 tx_byte_count_ = 456;
822 DeviceRefPtr device(new TestDevice(control_interface(),
823 dispatcher(),
824 NULL,
825 &manager_,
826 kDeviceName,
827 kDeviceAddress,
828 kDeviceInterfaceIndex,
829 Technology::kUnknown));
830 EXPECT_TRUE(ExpectByteCounts(device, 0, 0));
831
832 // Device should report any increase in the byte counts reported in the
833 // interface.
834 const int64 delta_rx_count = 789;
835 const int64 delta_tx_count = 12;
836 rx_byte_count_ += delta_rx_count;
837 tx_byte_count_ += delta_tx_count;
838 EXPECT_TRUE(ExpectByteCounts(device, delta_rx_count, delta_tx_count));
839
840 // Expect the correct values to be saved to the profile.
841 ExpectSavedCounts(device, delta_rx_count, delta_tx_count);
842
843 // If Device is loaded from a profile that does not contain stored byte
844 // counts, the byte counts reported should remain unchanged.
845 EXPECT_TRUE(device->Load(&storage_));
846 EXPECT_TRUE(ExpectByteCounts(device, delta_rx_count, delta_tx_count));
847
848 // If Device is loaded from a profile that contains stored byte
849 // counts, the byte counts reported should now reflect the stored values.
850 rx_stored_byte_count_ = 345;
851 tx_stored_byte_count_ = 678;
852 EXPECT_TRUE(device->Load(&storage_));
853 EXPECT_TRUE(ExpectByteCounts(
854 device, rx_stored_byte_count_, tx_stored_byte_count_));
855
856 // Increases to the interface receive count should be reflected as offsets
857 // to the stored byte counts.
858 rx_byte_count_ += delta_rx_count;
859 tx_byte_count_ += delta_tx_count;
860 EXPECT_TRUE(ExpectByteCounts(device,
861 rx_stored_byte_count_ + delta_rx_count,
862 tx_stored_byte_count_ + delta_tx_count));
863
864 // Expect the correct values to be saved to the profile.
865 ExpectSavedCounts(device,
866 rx_stored_byte_count_ + delta_rx_count,
867 tx_stored_byte_count_ + delta_tx_count);
868
869 // Expect that after resetting byte counts, read-back values return to zero,
870 // and that the device requests this information to be persisted.
871 EXPECT_CALL(manager_, UpdateDevice(device));
872 device->ResetByteCounters();
873 EXPECT_TRUE(ExpectByteCounts(device, 0, 0));
874}
875
Darin Petkovafa6fc42011-06-21 16:21:08 -0700876} // namespace shill