blob: 785253796364efcdb3a0a2e03390b3a65c57896b [file] [log] [blame]
Paul Stewartd8ad3c42012-01-09 12:39:38 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Chris Masone3bd3c8c2011-06-13 08:20:26 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/service.h"
6
7#include <map>
8#include <string>
9#include <vector>
10
Eric Shienbrood9a245532012-03-07 14:20:39 -050011#include <base/bind.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070012#include <chromeos/dbus/service_constants.h>
mukesh agrawal1830fa12011-09-26 14:31:40 -070013#include <dbus-c++/dbus.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070014#include <gtest/gtest.h>
15#include <gmock/gmock.h>
16
17#include "shill/dbus_adaptor.h"
18#include "shill/ethernet_service.h"
Paul Stewart26b327e2011-10-19 11:38:09 -070019#include "shill/event_dispatcher.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070020#include "shill/manager.h"
Chris Masone95207da2011-06-29 16:50:49 -070021#include "shill/mock_adaptors.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070022#include "shill/mock_control.h"
Paul Stewart10241e32012-04-23 18:15:06 -070023#include "shill/mock_connection.h"
24#include "shill/mock_device_info.h"
Darin Petkov385b9bc2012-12-03 15:25:05 +010025#include "shill/mock_diagnostics_reporter.h"
Christopher Wiley0801d192012-09-24 11:57:15 -070026#include "shill/mock_event_dispatcher.h"
Paul Stewartbc6e7392012-05-24 07:07:48 -070027#include "shill/mock_log.h"
Paul Stewart03dba0b2011-08-22 16:32:45 -070028#include "shill/mock_manager.h"
Darin Petkovcb0b5662012-12-13 09:59:44 +010029#include "shill/mock_power_manager.h"
Paul Stewartff14b022012-04-24 20:06:23 -070030#include "shill/mock_profile.h"
Darin Petkovcb0b5662012-12-13 09:59:44 +010031#include "shill/mock_proxy_factory.h"
Darin Petkovba40dd32011-07-11 20:06:39 -070032#include "shill/mock_store.h"
Darin Petkov385b9bc2012-12-03 15:25:05 +010033#include "shill/mock_time.h"
Paul Stewart8e7e4592012-04-29 09:47:48 -070034#include "shill/property_store_inspector.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070035#include "shill/property_store_unittest.h"
Chris Masone6515aab2011-10-12 16:19:09 -070036#include "shill/service_under_test.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070037
Eric Shienbrood9a245532012-03-07 14:20:39 -050038using base::Bind;
39using base::Unretained;
Darin Petkov385b9bc2012-12-03 15:25:05 +010040using std::deque;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070041using std::map;
42using std::string;
43using std::vector;
Darin Petkovba40dd32011-07-11 20:06:39 -070044using testing::_;
mukesh agrawalcf24a242012-05-21 16:46:11 -070045using testing::AnyNumber;
Darin Petkovba40dd32011-07-11 20:06:39 -070046using testing::AtLeast;
Paul Stewartd8ad3c42012-01-09 12:39:38 -080047using testing::DoAll;
Paul Stewartbc6e7392012-05-24 07:07:48 -070048using testing::HasSubstr;
Paul Stewart81426132012-05-16 10:05:10 -070049using testing::Mock;
Darin Petkovba40dd32011-07-11 20:06:39 -070050using testing::NiceMock;
51using testing::Return;
Paul Stewart10241e32012-04-23 18:15:06 -070052using testing::ReturnRef;
Darin Petkovba40dd32011-07-11 20:06:39 -070053using testing::StrictMock;
Paul Stewartd8ad3c42012-01-09 12:39:38 -080054using testing::SetArgumentPointee;
Darin Petkovba40dd32011-07-11 20:06:39 -070055using testing::Test;
Paul Stewart9f32d192012-01-30 20:37:50 -080056using testing::Values;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070057
58namespace shill {
59
60class ServiceTest : public PropertyStoreTest {
61 public:
Chris Masoneb925cc82011-06-22 15:39:57 -070062 ServiceTest()
Thieu Le3426c8f2012-01-11 17:35:11 -080063 : mock_manager_(control_interface(), dispatcher(), metrics(), glib()),
Chris Masone2176a882011-09-14 22:29:15 -070064 service_(new ServiceUnderTest(control_interface(),
65 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -080066 metrics(),
Paul Stewart03dba0b2011-08-22 16:32:45 -070067 &mock_manager_)),
Darin Petkovcb0b5662012-12-13 09:59:44 +010068 storage_id_(ServiceUnderTest::kStorageId),
69 power_manager_(new MockPowerManager(NULL, &proxy_factory_)) {
Darin Petkov385b9bc2012-12-03 15:25:05 +010070 service_->time_ = &time_;
71 service_->diagnostics_reporter_ = &diagnostics_reporter_;
Darin Petkovcb0b5662012-12-13 09:59:44 +010072 mock_manager_.running_ = true;
73 mock_manager_.set_power_manager(power_manager_); // Passes ownership.
Chris Masone9d779932011-08-25 16:33:41 -070074 }
Chris Masoneb925cc82011-06-22 15:39:57 -070075
Chris Masone3bd3c8c2011-06-13 08:20:26 -070076 virtual ~ServiceTest() {}
Chris Masoneb925cc82011-06-22 15:39:57 -070077
Eric Shienbrood9a245532012-03-07 14:20:39 -050078 MOCK_METHOD1(TestCallback, void(const Error &error));
79
Chris Masoneb925cc82011-06-22 15:39:57 -070080 protected:
mukesh agrawalcf24a242012-05-21 16:46:11 -070081 typedef scoped_refptr<MockProfile> MockProfileRefPtr;
Eric Shienbrood9a245532012-03-07 14:20:39 -050082
Darin Petkovcb0b5662012-12-13 09:59:44 +010083 class TestProxyFactory : public ProxyFactory {
84 public:
85 TestProxyFactory() {}
86
87 virtual PowerManagerProxyInterface *CreatePowerManagerProxy(
88 PowerManagerProxyDelegate *delegate) {
89 return NULL;
90 }
91
92 private:
93 DISALLOW_COPY_AND_ASSIGN(TestProxyFactory);
94 };
95
96 void SetManagerRunning(bool running) { mock_manager_.running_ = running; }
97
98 void SetPowerState(PowerManager::SuspendState state) {
99 power_manager_->power_state_ = state;
100 }
101
Darin Petkov385b9bc2012-12-03 15:25:05 +0100102 void SetExplicitlyDisconnected(bool explicitly) {
103 service_->explicitly_disconnected_ = explicitly;
104 }
105
106 void SetStateField(Service::ConnectState state) { service_->state_ = state; }
107
108 void NoteDisconnectEvent() {
109 service_->NoteDisconnectEvent();
110 }
111
112 deque<struct timeval> *GetDisconnects() { return &service_->disconnects_; }
113 deque<struct timeval> *GetMisconnects() { return &service_->misconnects_; }
114
115 int GetDisconnectsMonitorSeconds() {
116 return Service::kDisconnectsMonitorSeconds;
117 }
118
119 int GetMisconnectsMonitorSeconds() {
120 return Service::kMisconnectsMonitorSeconds;
121 }
122
123 int GetReportDisconnectsThreshold() {
124 return Service::kReportDisconnectsThreshold;
125 }
126
127 int GetReportMisconnectsThreshold() {
128 return Service::kReportMisconnectsThreshold;
129 }
130
131 int GetMaxDisconnectEventHistory() {
132 return Service::kMaxDisconnectEventHistory;
133 }
134
Paul Stewart03dba0b2011-08-22 16:32:45 -0700135 MockManager mock_manager_;
Darin Petkov385b9bc2012-12-03 15:25:05 +0100136 MockDiagnosticsReporter diagnostics_reporter_;
137 MockTime time_;
Paul Stewart03dba0b2011-08-22 16:32:45 -0700138 scoped_refptr<ServiceUnderTest> service_;
Chris Masone34af2182011-08-22 11:59:36 -0700139 string storage_id_;
Darin Petkovcb0b5662012-12-13 09:59:44 +0100140 TestProxyFactory proxy_factory_;
141 MockPowerManager *power_manager_; // Owned by |mock_manager_|.
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700142};
143
Christopher Wiley0801d192012-09-24 11:57:15 -0700144class AllMockServiceTest : public testing::Test {
145 public:
146 AllMockServiceTest()
147 : manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
148 service_(new ServiceUnderTest(&control_interface_,
149 &dispatcher_,
150 &metrics_,
151 &manager_)) { }
152 virtual ~AllMockServiceTest() {}
153
154 protected:
155 MockControl control_interface_;
156 StrictMock<MockEventDispatcher> dispatcher_;
157 MockGLib glib_;
158 NiceMock<MockMetrics> metrics_;
159 MockManager manager_;
160 scoped_refptr<ServiceUnderTest> service_;
161};
162
Darin Petkovba40dd32011-07-11 20:06:39 -0700163TEST_F(ServiceTest, Constructor) {
164 EXPECT_TRUE(service_->save_credentials_);
165 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400166 EXPECT_EQ(Service::kStateIdle, service_->state());
mukesh agrawalcf24a242012-05-21 16:46:11 -0700167 EXPECT_FALSE(service_->has_ever_connected());
Darin Petkovba40dd32011-07-11 20:06:39 -0700168}
169
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200170TEST_F(ServiceTest, CalculateState) {
171 service_->state_ = Service::kStateConnected;
172 Error error;
173 EXPECT_EQ(flimflam::kStateReady, service_->CalculateState(&error));
174 EXPECT_TRUE(error.IsSuccess());
175}
176
177TEST_F(ServiceTest, CalculateTechnology) {
178 service_->technology_ = Technology::kWifi;
179 Error error;
180 EXPECT_EQ(flimflam::kTypeWifi, service_->CalculateTechnology(&error));
181 EXPECT_TRUE(error.IsSuccess());
182}
183
Chris Masonea8a2c252011-06-27 22:16:30 -0700184TEST_F(ServiceTest, GetProperties) {
185 map<string, ::DBus::Variant> props;
186 Error error(Error::kInvalidProperty, "");
187 {
188 ::DBus::Error dbus_error;
Paul Stewartd215af62012-04-24 23:25:50 -0700189 string expected("true");
mukesh agrawalde29fa82011-09-16 16:16:36 -0700190 service_->mutable_store()->SetStringProperty(flimflam::kCheckPortalProperty,
191 expected,
192 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700193 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700194 ASSERT_FALSE(props.find(flimflam::kCheckPortalProperty) == props.end());
195 EXPECT_EQ(props[flimflam::kCheckPortalProperty].reader().get_string(),
196 expected);
197 }
198 {
199 ::DBus::Error dbus_error;
200 bool expected = true;
Thieu Le284fe792012-01-31 17:53:19 -0800201 service_->set_favorite(true);
mukesh agrawalde29fa82011-09-16 16:16:36 -0700202 service_->mutable_store()->SetBoolProperty(flimflam::kAutoConnectProperty,
203 expected,
204 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700205 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700206 ASSERT_FALSE(props.find(flimflam::kAutoConnectProperty) == props.end());
207 EXPECT_EQ(props[flimflam::kAutoConnectProperty].reader().get_bool(),
208 expected);
209 }
210 {
211 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -0700212 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700213 ASSERT_FALSE(props.find(flimflam::kConnectableProperty) == props.end());
214 EXPECT_EQ(props[flimflam::kConnectableProperty].reader().get_bool(), false);
215 }
216 {
217 ::DBus::Error dbus_error;
218 int32 expected = 127;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700219 service_->mutable_store()->SetInt32Property(flimflam::kPriorityProperty,
220 expected,
221 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700222 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700223 ASSERT_FALSE(props.find(flimflam::kPriorityProperty) == props.end());
224 EXPECT_EQ(props[flimflam::kPriorityProperty].reader().get_int32(),
225 expected);
226 }
Chris Masone95207da2011-06-29 16:50:49 -0700227 {
228 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -0700229 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masone95207da2011-06-29 16:50:49 -0700230 ASSERT_FALSE(props.find(flimflam::kDeviceProperty) == props.end());
Jason Glasgowacdc11f2012-03-30 14:12:22 -0400231 EXPECT_EQ(props[flimflam::kDeviceProperty].reader().get_path(),
Paul Stewart03dba0b2011-08-22 16:32:45 -0700232 string(ServiceUnderTest::kRpcId));
Chris Masone95207da2011-06-29 16:50:49 -0700233 }
Chris Masonea8a2c252011-06-27 22:16:30 -0700234}
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700235
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800236TEST_F(ServiceTest, SetProperty) {
Chris Masonea8a2c252011-06-27 22:16:30 -0700237 {
238 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800239 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
240 flimflam::kSaveCredentialsProperty,
241 PropertyStoreTest::kBoolV,
242 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700243 }
244 {
245 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800246 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
247 flimflam::kPriorityProperty,
248 PropertyStoreTest::kInt32V,
249 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700250 }
251 {
252 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800253 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
254 flimflam::kEAPEAPProperty,
255 PropertyStoreTest::kStringV,
256 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700257 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700258 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
Chris Masonea8a2c252011-06-27 22:16:30 -0700259 {
260 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800261 EXPECT_FALSE(DBusAdaptor::SetProperty(service_->mutable_store(),
262 flimflam::kFavoriteProperty,
263 PropertyStoreTest::kBoolV,
264 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700265 EXPECT_EQ(invalid_args(), error.name());
Chris Masonea8a2c252011-06-27 22:16:30 -0700266 }
Thieu Le284fe792012-01-31 17:53:19 -0800267 {
268 ::DBus::Error error;
269 service_->set_favorite(true);
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800270 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
271 flimflam::kAutoConnectProperty,
272 PropertyStoreTest::kBoolV,
273 &error));
Thieu Le284fe792012-01-31 17:53:19 -0800274 }
275 {
276 ::DBus::Error error;
277 service_->set_favorite(false);
Wade Guthrie4f28e8b2012-04-11 10:52:07 -0700278 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800279 flimflam::kAutoConnectProperty,
280 PropertyStoreTest::kBoolV,
281 &error));
Thieu Le284fe792012-01-31 17:53:19 -0800282 }
Paul Stewart0c438332012-04-11 07:55:27 -0700283 // Ensure that we can perform a trivial set of the Name property (to its
284 // current value) but an attempt to set the property to a different value
285 // fails.
286 {
287 ::DBus::Error error;
288 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
289 flimflam::kNameProperty,
290 DBusAdaptor::StringToVariant(
291 service_->friendly_name()),
292 &error));
293 }
294 {
295 ::DBus::Error error;
296 EXPECT_FALSE(DBusAdaptor::SetProperty(service_->mutable_store(),
297 flimflam::kNameProperty,
298 PropertyStoreTest::kStringV,
299 &error));
300 EXPECT_EQ(invalid_args(), error.name());
301 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700302}
303
Darin Petkovba40dd32011-07-11 20:06:39 -0700304TEST_F(ServiceTest, Load) {
305 NiceMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700306 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
307 EXPECT_CALL(storage, GetString(storage_id_, _, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700308 .Times(AtLeast(1))
309 .WillRepeatedly(Return(true));
Chris Masone9d779932011-08-25 16:33:41 -0700310 EXPECT_TRUE(service_->Load(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700311}
312
313TEST_F(ServiceTest, LoadFail) {
314 StrictMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700315 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(false));
Chris Masone9d779932011-08-25 16:33:41 -0700316 EXPECT_FALSE(service_->Load(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700317}
318
319TEST_F(ServiceTest, SaveString) {
320 MockStore storage;
321 static const char kKey[] = "test-key";
322 static const char kData[] = "test-data";
Chris Masone34af2182011-08-22 11:59:36 -0700323 EXPECT_CALL(storage, SetString(storage_id_, kKey, kData))
Darin Petkovba40dd32011-07-11 20:06:39 -0700324 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700325 service_->SaveString(&storage, storage_id_, kKey, kData, false, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700326}
327
328TEST_F(ServiceTest, SaveStringCrypted) {
329 MockStore storage;
330 static const char kKey[] = "test-key";
331 static const char kData[] = "test-data";
Chris Masone34af2182011-08-22 11:59:36 -0700332 EXPECT_CALL(storage, SetCryptedString(storage_id_, kKey, kData))
Darin Petkovba40dd32011-07-11 20:06:39 -0700333 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700334 service_->SaveString(&storage, storage_id_, kKey, kData, true, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700335}
336
337TEST_F(ServiceTest, SaveStringDontSave) {
338 MockStore storage;
339 static const char kKey[] = "test-key";
Chris Masone34af2182011-08-22 11:59:36 -0700340 EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
Darin Petkovba40dd32011-07-11 20:06:39 -0700341 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700342 service_->SaveString(&storage, storage_id_, kKey, "data", false, false);
Darin Petkovba40dd32011-07-11 20:06:39 -0700343}
344
345TEST_F(ServiceTest, SaveStringEmpty) {
346 MockStore storage;
347 static const char kKey[] = "test-key";
Chris Masone34af2182011-08-22 11:59:36 -0700348 EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
Darin Petkovba40dd32011-07-11 20:06:39 -0700349 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700350 service_->SaveString(&storage, storage_id_, kKey, "", true, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700351}
352
353TEST_F(ServiceTest, Save) {
354 NiceMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700355 EXPECT_CALL(storage, SetString(storage_id_, _, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700356 .Times(AtLeast(1))
357 .WillRepeatedly(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700358 EXPECT_CALL(storage, DeleteKey(storage_id_, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700359 .Times(AtLeast(1))
360 .WillRepeatedly(Return(true));
Chris Masone9d779932011-08-25 16:33:41 -0700361 EXPECT_TRUE(service_->Save(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700362}
363
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800364TEST_F(ServiceTest, Unload) {
365 NiceMock<MockStore> storage;
366 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
367 static const string string_value("value");
368 EXPECT_CALL(storage, GetString(storage_id_, _, _))
369 .Times(AtLeast(1))
370 .WillRepeatedly(DoAll(SetArgumentPointee<2>(string_value), Return(true)));
Paul Stewart88769de2012-09-21 13:14:36 -0700371 EXPECT_CALL(storage, GetBool(storage_id_, _, _))
372 .Times(AtLeast(1))
373 .WillRepeatedly(DoAll(SetArgumentPointee<2>(true), Return(true)));
374 EXPECT_FALSE(service_->explicitly_disconnected_);
375 service_->explicitly_disconnected_ = true;
376 EXPECT_FALSE(service_->has_ever_connected_);
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800377 ASSERT_TRUE(service_->Load(&storage));
Paul Stewarte7cce8f2012-09-11 10:56:38 -0700378 // TODO(pstew): Only two string properties in the service are tested as
mukesh agrawalcf24a242012-05-21 16:46:11 -0700379 // a sentinel that properties are being set and reset at the right times.
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800380 // However, since property load/store is essentially a manual process,
381 // it is error prone and should either be exhaustively unit-tested or
382 // a generic framework for registering loaded/stored properties should
383 // be created. crosbug.com/24859
384 EXPECT_EQ(string_value, service_->ui_data_);
Paul Stewarte7cce8f2012-09-11 10:56:38 -0700385 EXPECT_EQ(string_value, service_->guid_);
Paul Stewart88769de2012-09-21 13:14:36 -0700386 EXPECT_FALSE(service_->explicitly_disconnected_);
387 EXPECT_TRUE(service_->has_ever_connected_);
388 service_->explicitly_disconnected_ = true;
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800389 service_->Unload();
390 EXPECT_EQ(string(""), service_->ui_data_);
Paul Stewarte7cce8f2012-09-11 10:56:38 -0700391 EXPECT_EQ(string(""), service_->guid_);
Philipp Neubeckf883a7b2012-09-14 19:52:44 +0200392 EXPECT_FALSE(service_->explicitly_disconnected_);
Paul Stewart88769de2012-09-21 13:14:36 -0700393 EXPECT_FALSE(service_->has_ever_connected_);
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800394}
395
Paul Stewart03dba0b2011-08-22 16:32:45 -0700396TEST_F(ServiceTest, State) {
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400397 EXPECT_EQ(Service::kStateIdle, service_->state());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700398 EXPECT_EQ(Service::kFailureUnknown, service_->failure());
Paul Stewartf2d60912012-07-15 08:37:30 -0700399 const string unknown_error(
400 Service::ConnectFailureToString(Service::kFailureUnknown));
401 EXPECT_EQ(unknown_error, service_->error());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700402
mukesh agrawal00917ce2011-11-22 23:56:55 +0000403 ServiceRefPtr service_ref(service_);
mukesh agrawalf2f68a52011-09-01 12:15:48 -0700404
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400405 EXPECT_CALL(*dynamic_cast<ServiceMockAdaptor *>(service_->adaptor_.get()),
mukesh agrawalcf24a242012-05-21 16:46:11 -0700406 EmitStringChanged(flimflam::kStateProperty, _)).Times(7);
Paul Stewartf2d60912012-07-15 08:37:30 -0700407 EXPECT_CALL(*dynamic_cast<ServiceMockAdaptor *>(service_->adaptor_.get()),
408 EmitStringChanged(flimflam::kErrorProperty, _)).Times(4);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700409 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
410 service_->SetState(Service::kStateConnected);
411 // A second state change shouldn't cause another update
412 service_->SetState(Service::kStateConnected);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700413 EXPECT_EQ(Service::kStateConnected, service_->state());
414 EXPECT_EQ(Service::kFailureUnknown, service_->failure());
mukesh agrawalcf24a242012-05-21 16:46:11 -0700415 EXPECT_TRUE(service_->has_ever_connected_);
mukesh agrawal568b5c62012-02-28 14:44:47 -0800416
Paul Stewart03dba0b2011-08-22 16:32:45 -0700417 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
418 service_->SetState(Service::kStateDisconnected);
419
420 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
421 service_->SetFailure(Service::kFailureOutOfRange);
mukesh agrawal568b5c62012-02-28 14:44:47 -0800422 EXPECT_TRUE(service_->IsFailed());
423 EXPECT_GT(service_->failed_time_, 0);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700424 EXPECT_EQ(Service::kStateFailure, service_->state());
425 EXPECT_EQ(Service::kFailureOutOfRange, service_->failure());
Paul Stewartf2d60912012-07-15 08:37:30 -0700426 const string out_of_range_error(
427 Service::ConnectFailureToString(Service::kFailureOutOfRange));
428 EXPECT_EQ(out_of_range_error, service_->error());
mukesh agrawal568b5c62012-02-28 14:44:47 -0800429
430 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
431 service_->SetState(Service::kStateConnected);
432 EXPECT_FALSE(service_->IsFailed());
433 EXPECT_EQ(service_->failed_time_, 0);
Paul Stewartf2d60912012-07-15 08:37:30 -0700434 EXPECT_EQ(unknown_error, service_->error());
mukesh agrawal568b5c62012-02-28 14:44:47 -0800435
436 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
437 service_->SetFailureSilent(Service::kFailurePinMissing);
438 EXPECT_TRUE(service_->IsFailed());
439 EXPECT_GT(service_->failed_time_, 0);
440 EXPECT_EQ(Service::kStateIdle, service_->state());
441 EXPECT_EQ(Service::kFailurePinMissing, service_->failure());
Paul Stewartf2d60912012-07-15 08:37:30 -0700442 const string pin_missing_error(
443 Service::ConnectFailureToString(Service::kFailurePinMissing));
444 EXPECT_EQ(pin_missing_error, service_->error());
mukesh agrawalcf24a242012-05-21 16:46:11 -0700445
446 // If the Service has a Profile, the profile should be saved when
447 // the service enters kStateConnected. (The case where the service
448 // doesn't have a profile is tested above.)
449 MockProfileRefPtr mock_profile(
450 new MockProfile(control_interface(), &mock_manager_));
451 NiceMock<MockStore> storage;
452 service_->set_profile(mock_profile);
453 service_->has_ever_connected_ = false;
454 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
455 EXPECT_CALL(*mock_profile, GetConstStorage())
456 .WillOnce(Return(&storage));
457 EXPECT_CALL(*mock_profile, UpdateService(service_ref));
458 service_->SetState(Service::kStateConnected);
459 EXPECT_TRUE(service_->has_ever_connected_);
460 service_->set_profile(NULL); // Break reference cycle.
461
462 // Similar to the above, but emulate an emphemeral profile, which
463 // has no storage. We can't update the service in the profile, but
464 // we should not crash.
465 service_->state_ = Service::kStateIdle; // Skips state change logic.
466 service_->set_profile(mock_profile);
467 service_->has_ever_connected_ = false;
468 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
469 EXPECT_CALL(*mock_profile, GetConstStorage()).
470 WillOnce(Return(static_cast<StoreInterface *>(NULL)));
471 service_->SetState(Service::kStateConnected);
472 EXPECT_TRUE(service_->has_ever_connected_);
473 service_->set_profile(NULL); // Break reference cycle.
Paul Stewart03dba0b2011-08-22 16:32:45 -0700474}
475
Darin Petkovb100ae72011-08-24 16:19:45 -0700476TEST_F(ServiceTest, ActivateCellularModem) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500477 ResultCallback callback =
478 Bind(&ServiceTest::TestCallback, Unretained(this));
479 EXPECT_CALL(*this, TestCallback(_)).Times(0);
Darin Petkovb100ae72011-08-24 16:19:45 -0700480 Error error;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500481 service_->ActivateCellularModem("Carrier", &error, callback);
482 EXPECT_TRUE(error.IsFailure());
Darin Petkovb100ae72011-08-24 16:19:45 -0700483}
484
mukesh agrawal00917ce2011-11-22 23:56:55 +0000485TEST_F(ServiceTest, MakeFavorite) {
486 EXPECT_FALSE(service_->favorite());
487 EXPECT_FALSE(service_->auto_connect());
488
489 service_->MakeFavorite();
490 EXPECT_TRUE(service_->favorite());
491 EXPECT_TRUE(service_->auto_connect());
492}
493
494TEST_F(ServiceTest, ReMakeFavorite) {
495 service_->MakeFavorite();
496 EXPECT_TRUE(service_->favorite());
497 EXPECT_TRUE(service_->auto_connect());
498
499 service_->set_auto_connect(false);
500 service_->MakeFavorite();
501 EXPECT_TRUE(service_->favorite());
502 EXPECT_FALSE(service_->auto_connect());
503}
504
mukesh agrawal76d13882012-01-12 15:23:11 -0800505TEST_F(ServiceTest, IsAutoConnectable) {
mukesh agrawalbf14e942012-03-02 14:36:34 -0800506 const char *reason;
mukesh agrawal76d13882012-01-12 15:23:11 -0800507 service_->set_connectable(true);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800508 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawal76d13882012-01-12 15:23:11 -0800509
mukesh agrawaladb68482012-01-17 16:31:51 -0800510 // We should not auto-connect to a Service that a user has
511 // deliberately disconnected.
512 Error error;
Christopher Wileyabd3b502012-09-26 13:08:52 -0700513 service_->UserInitiatedDisconnect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800514 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
515 EXPECT_STREQ(Service::kAutoConnExplicitDisconnect, reason);
mukesh agrawaladb68482012-01-17 16:31:51 -0800516
517 // But if the Service is reloaded, it is eligible for auto-connect
518 // again.
519 NiceMock<MockStore> storage;
520 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
521 EXPECT_TRUE(service_->Load(&storage));
mukesh agrawalbf14e942012-03-02 14:36:34 -0800522 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800523
524 // A deliberate Connect should also re-enable auto-connect.
Christopher Wileyabd3b502012-09-26 13:08:52 -0700525 service_->UserInitiatedDisconnect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800526 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800527 service_->Connect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800528 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800529
Christopher Wileyabd3b502012-09-26 13:08:52 -0700530 // A non-user initiated Disconnect doesn't change anything.
531 service_->Disconnect(&error);
532 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
533
Christopher Wileya4c61ae2012-10-01 11:04:30 -0700534 // A resume also re-enables auto-connect.
535 service_->UserInitiatedDisconnect(&error);
536 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
537 service_->OnAfterResume();
538 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800539
mukesh agrawal76d13882012-01-12 15:23:11 -0800540 service_->SetState(Service::kStateConnected);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800541 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
542 EXPECT_STREQ(Service::kAutoConnConnected, reason);
mukesh agrawal76d13882012-01-12 15:23:11 -0800543
544 service_->SetState(Service::kStateAssociating);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800545 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
546 EXPECT_STREQ(Service::kAutoConnConnecting, reason);
mukesh agrawal76d13882012-01-12 15:23:11 -0800547}
548
mukesh agrawal03c15ce2012-11-29 17:36:21 -0800549TEST_F(ServiceTest, AutoConnectLogging) {
550 ScopedMockLog log;
551 EXPECT_CALL(log, Log(_, _, _));
552 service_->set_connectable(true);
553
554 ScopeLogger::GetInstance()->EnableScopesByName("+service");
555 ScopeLogger::GetInstance()->set_verbose_level(1);
556 service_->SetState(Service::kStateConnected);
557 EXPECT_CALL(log, Log(-1, _, HasSubstr(Service::kAutoConnConnected)));
558 service_->AutoConnect();
559
560 ScopeLogger::GetInstance()->EnableScopesByName("-service");
561 ScopeLogger::GetInstance()->set_verbose_level(0);
562 EXPECT_CALL(log, Log(logging::LOG_INFO, _,
563 HasSubstr(Service::kAutoConnNotConnectable)));
564 service_->set_connectable(false);
565 service_->AutoConnect();
566}
567
568
Christopher Wiley0801d192012-09-24 11:57:15 -0700569TEST_F(AllMockServiceTest, AutoConnectWithFailures) {
570 const char *reason;
571 service_->set_connectable(true);
572 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
573
574 // The very first AutoConnect() doesn't trigger any throttling.
575 EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(0);
576 service_->AutoConnect();
577 Mock::VerifyAndClearExpectations(&dispatcher_);
578 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
579
580 // The second call does trigger some throttling.
581 EXPECT_CALL(dispatcher_, PostDelayedTask(_,
582 Service::kMinAutoConnectCooldownTimeMilliseconds));
583 service_->AutoConnect();
584 Mock::VerifyAndClearExpectations(&dispatcher_);
585 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
586 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
587
588 // Calling AutoConnect() again before the cooldown terminates does not change
589 // the timeout.
590 EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(0);
591 service_->AutoConnect();
592 Mock::VerifyAndClearExpectations(&dispatcher_);
593 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
594 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
595
596 // Once the timeout expires, we can AutoConnect() again.
597 service_->ReEnableAutoConnectTask();
598 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
599
600 // Timeouts increase exponentially.
601 uint64 next_cooldown_time = service_->auto_connect_cooldown_milliseconds_;
602 EXPECT_EQ(next_cooldown_time,
603 Service::kAutoConnectCooldownBackoffFactor *
604 Service::kMinAutoConnectCooldownTimeMilliseconds);
605 while (next_cooldown_time <=
606 Service::kMaxAutoConnectCooldownTimeMilliseconds) {
607 EXPECT_CALL(dispatcher_, PostDelayedTask(_, next_cooldown_time));
608 service_->AutoConnect();
609 Mock::VerifyAndClearExpectations(&dispatcher_);
610 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
611 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
612 service_->ReEnableAutoConnectTask();
613 next_cooldown_time *= Service::kAutoConnectCooldownBackoffFactor;
614 }
615
616 // Once we hit our cap, future timeouts are the same.
617 for (int32 i = 0; i < 2; i++) {
618 EXPECT_CALL(dispatcher_, PostDelayedTask(_,
619 Service::kMaxAutoConnectCooldownTimeMilliseconds));
620 service_->AutoConnect();
621 Mock::VerifyAndClearExpectations(&dispatcher_);
622 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
623 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
624 service_->ReEnableAutoConnectTask();
625 }
626
627 // Connecting successfully resets our cooldown.
628 service_->SetState(Service::kStateConnected);
629 service_->SetState(Service::kStateIdle);
630 reason = "";
631 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
632 EXPECT_STREQ("", reason);
633 EXPECT_EQ(service_->auto_connect_cooldown_milliseconds_, 0);
634
635 // But future AutoConnects behave as before
636 EXPECT_CALL(dispatcher_, PostDelayedTask(_,
637 Service::kMinAutoConnectCooldownTimeMilliseconds)).Times(1);
638 service_->AutoConnect();
639 service_->AutoConnect();
640 Mock::VerifyAndClearExpectations(&dispatcher_);
641 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
642 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
643
644 // Cooldowns are forgotten if we go through a suspend/resume cycle.
645 service_->OnAfterResume();
646 reason = "";
647 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
648 EXPECT_STREQ("", reason);
649}
650
Paul Stewartcb59fed2012-03-21 21:14:46 -0700651TEST_F(ServiceTest, ConfigureBadProperty) {
652 KeyValueStore args;
653 args.SetString("XXXInvalid", "Value");
654 Error error;
655 service_->Configure(args, &error);
656 EXPECT_FALSE(error.IsSuccess());
657}
658
659TEST_F(ServiceTest, ConfigureBoolProperty) {
660 service_->MakeFavorite();
661 service_->set_auto_connect(false);
662 ASSERT_FALSE(service_->auto_connect());
663 KeyValueStore args;
664 args.SetBool(flimflam::kAutoConnectProperty, true);
665 Error error;
666 service_->Configure(args, &error);
667 EXPECT_TRUE(error.IsSuccess());
668 EXPECT_TRUE(service_->auto_connect());
669}
670
671TEST_F(ServiceTest, ConfigureStringProperty) {
672 const string kEAPManagement0 = "management_zero";
673 const string kEAPManagement1 = "management_one";
674 service_->SetEAPKeyManagement(kEAPManagement0);
675 ASSERT_EQ(kEAPManagement0, service_->GetEAPKeyManagement());
676 KeyValueStore args;
677 args.SetString(flimflam::kEapKeyMgmtProperty, kEAPManagement1);
678 Error error;
679 service_->Configure(args, &error);
680 EXPECT_TRUE(error.IsSuccess());
681 EXPECT_EQ(kEAPManagement1, service_->GetEAPKeyManagement());
682}
683
684TEST_F(ServiceTest, ConfigureIgnoredProperty) {
685 service_->MakeFavorite();
686 service_->set_auto_connect(false);
687 ASSERT_FALSE(service_->auto_connect());
688 KeyValueStore args;
689 args.SetBool(flimflam::kAutoConnectProperty, true);
690 Error error;
691 service_->IgnoreParameterForConfigure(flimflam::kAutoConnectProperty);
692 service_->Configure(args, &error);
693 EXPECT_TRUE(error.IsSuccess());
694 EXPECT_FALSE(service_->auto_connect());
695}
696
Paul Stewart10ccbb32012-04-26 15:59:30 -0700697TEST_F(ServiceTest, IsRemembered) {
698 ServiceConstRefPtr service_ref(service_);
699 service_->set_profile(NULL);
700 EXPECT_CALL(mock_manager_, IsServiceEphemeral(_)).Times(0);
701 EXPECT_FALSE(service_->IsRemembered());
702
703 scoped_refptr<MockProfile> profile(
704 new StrictMock<MockProfile>(control_interface(), manager()));
705 service_->set_profile(profile);
706 EXPECT_CALL(mock_manager_, IsServiceEphemeral(service_ref))
707 .WillOnce(Return(true))
708 .WillOnce(Return(false));
709 EXPECT_FALSE(service_->IsRemembered());
710 EXPECT_TRUE(service_->IsRemembered());
711}
712
Paul Stewartdf3c0a82012-11-09 15:54:33 -0800713TEST_F(ServiceTest, IsDependentOn) {
714 EXPECT_FALSE(service_->IsDependentOn(NULL));
715
716 scoped_ptr<MockDeviceInfo> mock_device_info(
717 new NiceMock<MockDeviceInfo>(control_interface(), dispatcher(), metrics(),
718 &mock_manager_));
719 scoped_refptr<MockConnection> mock_connection0(
720 new NiceMock<MockConnection>(mock_device_info.get()));
721 scoped_refptr<MockConnection> mock_connection1(
722 new NiceMock<MockConnection>(mock_device_info.get()));
723
724 service_->connection_ = mock_connection0;
725 EXPECT_CALL(*mock_connection0.get(), GetLowerConnection())
726 .WillRepeatedly(Return(mock_connection1));
727 EXPECT_FALSE(service_->IsDependentOn(NULL));
728
729 scoped_refptr<ServiceUnderTest> service1 =
730 new ServiceUnderTest(control_interface(),
731 dispatcher(),
732 metrics(),
733 &mock_manager_);
734 EXPECT_FALSE(service_->IsDependentOn(service1));
735
736 service1->connection_ = mock_connection0;
737 EXPECT_FALSE(service_->IsDependentOn(service1));
738
739 service1->connection_ = mock_connection1;
740 EXPECT_TRUE(service_->IsDependentOn(service1));
741
742 service_->connection_ = NULL;
743 service1->connection_ = NULL;
744}
745
Paul Stewartff14b022012-04-24 20:06:23 -0700746TEST_F(ServiceTest, OnPropertyChanged) {
747 scoped_refptr<MockProfile> profile(
748 new StrictMock<MockProfile>(control_interface(), manager()));
749 service_->set_profile(NULL);
750 // Expect no crash.
751 service_->OnPropertyChanged("");
752
753 // Expect no call to Update if the profile has no storage.
754 service_->set_profile(profile);
755 EXPECT_CALL(*profile, UpdateService(_)).Times(0);
756 EXPECT_CALL(*profile, GetConstStorage())
757 .WillOnce(Return(reinterpret_cast<StoreInterface *>(NULL)));
758 service_->OnPropertyChanged("");
759
760 // Expect call to Update if the profile has storage.
761 EXPECT_CALL(*profile, UpdateService(_)).Times(1);
762 NiceMock<MockStore> storage;
763 EXPECT_CALL(*profile, GetConstStorage()).WillOnce(Return(&storage));
764 service_->OnPropertyChanged("");
765}
766
Paul Stewartd215af62012-04-24 23:25:50 -0700767
768TEST_F(ServiceTest, RecheckPortal) {
769 ServiceRefPtr service_ref(service_);
770 service_->state_ = Service::kStateIdle;
771 EXPECT_CALL(mock_manager_, RecheckPortalOnService(_)).Times(0);
772 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
773
774 service_->state_ = Service::kStatePortal;
775 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
776 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
777
778 service_->state_ = Service::kStateConnected;
779 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
780 service_->OnPropertyChanged(flimflam::kProxyConfigProperty);
781
782 service_->state_ = Service::kStateOnline;
783 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
784 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
785
786 service_->state_ = Service::kStatePortal;
787 EXPECT_CALL(mock_manager_, RecheckPortalOnService(_)).Times(0);
788 service_->OnPropertyChanged(flimflam::kEAPKeyIDProperty);
789}
790
791TEST_F(ServiceTest, SetCheckPortal) {
792 ServiceRefPtr service_ref(service_);
793 {
794 Error error;
795 service_->SetCheckPortal("false", &error);
796 EXPECT_TRUE(error.IsSuccess());
797 EXPECT_EQ(Service::kCheckPortalFalse, service_->check_portal_);
798 }
799 {
800 Error error;
801 service_->SetCheckPortal("true", &error);
802 EXPECT_TRUE(error.IsSuccess());
803 EXPECT_EQ(Service::kCheckPortalTrue, service_->check_portal_);
804 }
805 {
806 Error error;
807 service_->SetCheckPortal("auto", &error);
808 EXPECT_TRUE(error.IsSuccess());
809 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
810 }
811 {
812 Error error;
813 service_->SetCheckPortal("xxx", &error);
814 EXPECT_FALSE(error.IsSuccess());
815 EXPECT_EQ(Error::kInvalidArguments, error.type());
816 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
817 }
818}
819
Darin Petkovb2ba39f2012-06-06 10:33:43 +0200820TEST_F(ServiceTest, SetConnectable) {
821 EXPECT_FALSE(service_->connectable());
822
823 ServiceMockAdaptor *adaptor =
824 dynamic_cast<ServiceMockAdaptor *>(service_->adaptor());
825
826 EXPECT_CALL(*adaptor, EmitBoolChanged(_, _)).Times(0);
827 EXPECT_CALL(mock_manager_, HasService(_)).Times(0);
828 service_->SetConnectable(false);
829 EXPECT_FALSE(service_->connectable());
830
831 EXPECT_CALL(*adaptor, EmitBoolChanged(flimflam::kConnectableProperty, true));
832 EXPECT_CALL(mock_manager_, HasService(_)).WillOnce(Return(false));
833 EXPECT_CALL(mock_manager_, UpdateService(_)).Times(0);
834 service_->SetConnectable(true);
835 EXPECT_TRUE(service_->connectable());
836
837 EXPECT_CALL(*adaptor, EmitBoolChanged(flimflam::kConnectableProperty, false));
838 EXPECT_CALL(mock_manager_, HasService(_)).WillOnce(Return(true));
839 EXPECT_CALL(mock_manager_, UpdateService(_));
840 service_->SetConnectable(false);
841 EXPECT_FALSE(service_->connectable());
842
843 EXPECT_CALL(*adaptor, EmitBoolChanged(flimflam::kConnectableProperty, true));
844 EXPECT_CALL(mock_manager_, HasService(_)).WillOnce(Return(true));
845 EXPECT_CALL(mock_manager_, UpdateService(_));
846 service_->SetConnectable(true);
847 EXPECT_TRUE(service_->connectable());
848}
849
Paul Stewart9f32d192012-01-30 20:37:50 -0800850// Make sure a property is registered as a write only property
851// by reading and comparing all string properties returned on the store.
852// Subtle: We need to convert the test argument back and forth between
853// string and ::DBus::Variant because this is the parameter type that
854// our supeclass (PropertyStoreTest) is declared with.
855class ReadOnlyServicePropertyTest : public ServiceTest {};
856TEST_P(ReadOnlyServicePropertyTest, PropertyWriteOnly) {
Paul Stewart9f32d192012-01-30 20:37:50 -0800857 string property(GetParam().reader().get_string());
Paul Stewart8e7e4592012-04-29 09:47:48 -0700858 PropertyStoreInspector inspector(&service_->store());
Darin Petkov4682aa82012-05-31 16:24:11 +0200859 EXPECT_FALSE(inspector.GetStringProperty(property, NULL));
Paul Stewart9f32d192012-01-30 20:37:50 -0800860}
861
862INSTANTIATE_TEST_CASE_P(
863 ReadOnlyServicePropertyTestInstance,
864 ReadOnlyServicePropertyTest,
865 Values(
866 DBusAdaptor::StringToVariant(flimflam::kEapPrivateKeyPasswordProperty),
867 DBusAdaptor::StringToVariant(flimflam::kEapPasswordProperty)));
868
Paul Stewart10241e32012-04-23 18:15:06 -0700869
870TEST_F(ServiceTest, GetIPConfigRpcIdentifier) {
871 {
872 Error error;
873 EXPECT_EQ("/", service_->GetIPConfigRpcIdentifier(&error));
874 EXPECT_EQ(Error::kNotFound, error.type());
875 }
876
877 scoped_ptr<MockDeviceInfo> mock_device_info(
878 new NiceMock<MockDeviceInfo>(control_interface(), dispatcher(), metrics(),
879 &mock_manager_));
880 scoped_refptr<MockConnection> mock_connection(
881 new NiceMock<MockConnection>(mock_device_info.get()));
882
883 service_->connection_ = mock_connection;
884
885 {
886 Error error;
887 const string empty_string;
888 EXPECT_CALL(*mock_connection, ipconfig_rpc_identifier())
889 .WillOnce(ReturnRef(empty_string));
890 EXPECT_EQ("/", service_->GetIPConfigRpcIdentifier(&error));
891 EXPECT_EQ(Error::kNotFound, error.type());
892 }
893
894 {
895 Error error;
896 const string nonempty_string("/ipconfig/path");
897 EXPECT_CALL(*mock_connection, ipconfig_rpc_identifier())
898 .WillOnce(ReturnRef(nonempty_string));
899 EXPECT_EQ(nonempty_string, service_->GetIPConfigRpcIdentifier(&error));
900 EXPECT_EQ(Error::kSuccess, error.type());
901 }
902
903 // Assure orderly destruction of the Connection before DeviceInfo.
904 service_->connection_ = NULL;
905 mock_connection = NULL;
906 mock_device_info.reset();
907}
908
Paul Stewart81426132012-05-16 10:05:10 -0700909class ServiceWithMockSetEap : public ServiceUnderTest {
910 public:
911 ServiceWithMockSetEap(ControlInterface *control_interface,
912 EventDispatcher *dispatcher,
913 Metrics *metrics,
914 Manager *manager)
915 : ServiceUnderTest(control_interface, dispatcher, metrics, manager),
916 is_8021x_(false) {}
917 MOCK_METHOD1(set_eap, void(const EapCredentials &eap));
918 virtual bool Is8021x() const { return is_8021x_; }
919 void set_is_8021x(bool is_8021x) { is_8021x_ = is_8021x; }
920
921 private:
922 bool is_8021x_;
923};
924
925TEST_F(ServiceTest, SetEAPCredentialsOverRPC) {
926 scoped_refptr<ServiceWithMockSetEap> service(
927 new ServiceWithMockSetEap(control_interface(),
928 dispatcher(),
929 metrics(),
930 &mock_manager_));
931 string eap_credential_properties[] = {
932 flimflam::kEAPCertIDProperty,
933 flimflam::kEAPClientCertProperty,
934 flimflam::kEAPKeyIDProperty,
935 flimflam::kEAPPINProperty,
936 flimflam::kEapCaCertIDProperty,
937 flimflam::kEapIdentityProperty,
938 flimflam::kEapPasswordProperty,
939 flimflam::kEapPrivateKeyProperty
940 };
941 string eap_non_credential_properties[] = {
942 flimflam::kEAPEAPProperty,
943 flimflam::kEapPhase2AuthProperty,
944 flimflam::kEapAnonymousIdentityProperty,
945 flimflam::kEapPrivateKeyPasswordProperty,
Paul Stewart81426132012-05-16 10:05:10 -0700946 flimflam::kEapCaCertNssProperty,
947 flimflam::kEapUseSystemCAsProperty
948 };
949 // While this is not an 802.1x-based service, none of these property
950 // changes should cause a call to set_eap().
951 EXPECT_CALL(*service, set_eap(_)).Times(0);
952 for (size_t i = 0; i < arraysize(eap_credential_properties); ++i)
953 service->OnPropertyChanged(eap_credential_properties[i]);
954 for (size_t i = 0; i < arraysize(eap_non_credential_properties); ++i)
955 service->OnPropertyChanged(eap_non_credential_properties[i]);
Paul Stewartadf79d82012-07-18 16:09:56 -0700956 service->OnPropertyChanged(flimflam::kEapKeyMgmtProperty);
Paul Stewart81426132012-05-16 10:05:10 -0700957
958 service->set_is_8021x(true);
959
960 // When this is an 802.1x-based service, set_eap should be called for
961 // all credential-carrying properties.
962 for (size_t i = 0; i < arraysize(eap_credential_properties); ++i) {
963 EXPECT_CALL(*service, set_eap(_)).Times(1);
964 service->OnPropertyChanged(eap_credential_properties[i]);
965 Mock::VerifyAndClearExpectations(service.get());
966 }
Paul Stewartadf79d82012-07-18 16:09:56 -0700967
968 // The key management property is a special case. While not strictly
969 // a credential, it can change which credentials are used. Therefore it
970 // should also trigger a call to set_eap();
971 EXPECT_CALL(*service, set_eap(_)).Times(1);
972 service->OnPropertyChanged(flimflam::kEapKeyMgmtProperty);
973 Mock::VerifyAndClearExpectations(service.get());
974
Paul Stewart81426132012-05-16 10:05:10 -0700975 EXPECT_CALL(*service, set_eap(_)).Times(0);
976 for (size_t i = 0; i < arraysize(eap_non_credential_properties); ++i)
977 service->OnPropertyChanged(eap_non_credential_properties[i]);
978}
979
Paul Stewartbc6e7392012-05-24 07:07:48 -0700980TEST_F(ServiceTest, Certification) {
981 EXPECT_FALSE(service_->eap_.remote_certification.size());
982
983 ScopedMockLog log;
984 EXPECT_CALL(log, Log(logging::LOG_WARNING, _,
985 HasSubstr("exceeds our maximum"))).Times(2);
986 string kSubject("foo");
987 EXPECT_FALSE(service_->AddEAPCertification(
988 kSubject, Service::kEAPMaxCertificationElements));
989 EXPECT_FALSE(service_->AddEAPCertification(
990 kSubject, Service::kEAPMaxCertificationElements + 1));
991 EXPECT_FALSE(service_->eap_.remote_certification.size());
992 Mock::VerifyAndClearExpectations(&log);
993
994 EXPECT_CALL(log,
995 Log(logging::LOG_INFO, _, HasSubstr("Received certification")))
996 .Times(1);
997 EXPECT_TRUE(service_->AddEAPCertification(
998 kSubject, Service::kEAPMaxCertificationElements - 1));
999 Mock::VerifyAndClearExpectations(&log);
1000 EXPECT_EQ(Service::kEAPMaxCertificationElements,
1001 service_->eap_.remote_certification.size());
1002 for (size_t i = 0; i < Service::kEAPMaxCertificationElements - 1; ++i) {
1003 EXPECT_TRUE(service_->eap_.remote_certification[i].empty());
1004 }
1005 EXPECT_EQ(kSubject, service_->eap_.remote_certification[
1006 Service::kEAPMaxCertificationElements - 1]);
1007
1008 // Re-adding the same name in the same position should not generate a log.
1009 EXPECT_CALL(log, Log(_, _, _)).Times(0);
1010 EXPECT_TRUE(service_->AddEAPCertification(
1011 kSubject, Service::kEAPMaxCertificationElements - 1));
1012
1013 // Replacing the item should generate a log message.
1014 EXPECT_CALL(log,
1015 Log(logging::LOG_INFO, _, HasSubstr("Received certification")))
1016 .Times(1);
1017 EXPECT_TRUE(service_->AddEAPCertification(
1018 kSubject + "x", Service::kEAPMaxCertificationElements - 1));
1019}
1020
Darin Petkov385b9bc2012-12-03 15:25:05 +01001021TEST_F(ServiceTest, NoteDisconnectEventInvoked) {
1022 EXPECT_CALL(time_, GetTimeMonotonic(_))
1023 .WillOnce(DoAll(SetArgumentPointee<0>((const struct timeval){ 0 }),
1024 Return(0)));
1025 SetStateField(Service::kStateOnline);
1026 service_->SetState(Service::kStateIdle);
1027 EXPECT_FALSE(GetDisconnects()->empty());
1028}
1029
1030TEST_F(ServiceTest, NoteDisconnectEventNonEvent) {
1031 EXPECT_CALL(time_, GetTimeMonotonic(_)).Times(0);
1032 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(0);
1033
1034 // Explicit disconnect is a non-event.
1035 SetStateField(Service::kStateOnline);
1036 SetExplicitlyDisconnected(true);
1037 NoteDisconnectEvent();
1038 EXPECT_TRUE(GetDisconnects()->empty());
1039 EXPECT_TRUE(GetMisconnects()->empty());
1040
1041 // Failure to idle transition is a non-event.
1042 SetStateField(Service::kStateFailure);
1043 SetExplicitlyDisconnected(false);
1044 NoteDisconnectEvent();
1045 EXPECT_TRUE(GetDisconnects()->empty());
1046 EXPECT_TRUE(GetMisconnects()->empty());
Darin Petkovcb0b5662012-12-13 09:59:44 +01001047
1048 // Disconnect while manager is stopped is a non-event.
1049 SetStateField(Service::kStateOnline);
1050 SetManagerRunning(false);
1051 NoteDisconnectEvent();
1052 EXPECT_TRUE(GetDisconnects()->empty());
1053 EXPECT_TRUE(GetMisconnects()->empty());
1054
1055 // Disconnect while suspending is a non-event.
1056 SetManagerRunning(true);
1057 SetPowerState(PowerManager::kSuspending);
1058 NoteDisconnectEvent();
1059 EXPECT_TRUE(GetDisconnects()->empty());
1060 EXPECT_TRUE(GetMisconnects()->empty());
Darin Petkov385b9bc2012-12-03 15:25:05 +01001061}
1062
1063TEST_F(ServiceTest, NoteDisconnectEventDisconnectOnce) {
1064 EXPECT_FALSE(service_->explicitly_disconnected());
1065 SetStateField(Service::kStateOnline);
1066 static const struct timeval now = { .tv_sec = 5, .tv_usec = 0 };
1067 EXPECT_CALL(time_, GetTimeMonotonic(_))
1068 .WillOnce(DoAll(SetArgumentPointee<0>(now), Return(0)));
1069 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(0);
1070 NoteDisconnectEvent();
1071 ASSERT_EQ(1, GetDisconnects()->size());
1072 EXPECT_EQ(now.tv_sec, GetDisconnects()->front().tv_sec);
1073 EXPECT_TRUE(GetMisconnects()->empty());
1074}
1075
1076TEST_F(ServiceTest, NoteDisconnectEventDisconnectThreshold) {
1077 EXPECT_FALSE(service_->explicitly_disconnected());
1078 SetStateField(Service::kStateOnline);
1079 static const struct timeval now = { .tv_sec = 5, .tv_usec = 0 };
1080 for (int i = 0; i < GetReportDisconnectsThreshold() - 1; i++) {
1081 GetDisconnects()->push_back(now);
1082 }
1083 EXPECT_CALL(time_, GetTimeMonotonic(_))
1084 .WillOnce(DoAll(SetArgumentPointee<0>(now), Return(0)));
1085 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(1);
1086 NoteDisconnectEvent();
1087 EXPECT_EQ(GetReportDisconnectsThreshold(), GetDisconnects()->size());
1088}
1089
1090TEST_F(ServiceTest, NoteDisconnectEventMisconnectOnce) {
1091 EXPECT_FALSE(service_->explicitly_disconnected());
1092 SetStateField(Service::kStateConfiguring);
1093 static const struct timeval now = { .tv_sec = 7, .tv_usec = 0 };
1094 EXPECT_CALL(time_, GetTimeMonotonic(_))
1095 .WillOnce(DoAll(SetArgumentPointee<0>(now), Return(0)));
1096 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(0);
1097 NoteDisconnectEvent();
1098 EXPECT_TRUE(GetDisconnects()->empty());
1099 ASSERT_EQ(1, GetMisconnects()->size());
1100 EXPECT_EQ(now.tv_sec, GetMisconnects()->front().tv_sec);
1101}
1102
1103TEST_F(ServiceTest, NoteDisconnectEventMisconnectThreshold) {
1104 EXPECT_FALSE(service_->explicitly_disconnected());
1105 SetStateField(Service::kStateConfiguring);
1106 static const struct timeval now = { .tv_sec = 7, .tv_usec = 0 };
1107 for (int i = 0; i < GetReportMisconnectsThreshold() - 1; i++) {
1108 GetMisconnects()->push_back(now);
1109 }
1110 EXPECT_CALL(time_, GetTimeMonotonic(_))
1111 .WillOnce(DoAll(SetArgumentPointee<0>(now), Return(0)));
1112 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(1);
1113 NoteDisconnectEvent();
1114 EXPECT_EQ(GetReportMisconnectsThreshold(), GetMisconnects()->size());
1115}
1116
1117TEST_F(ServiceTest, NoteDisconnectEventDiscardOld) {
1118 EXPECT_FALSE(service_->explicitly_disconnected());
1119 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(0);
1120 for (int i = 0; i < 2; i++) {
1121 struct timeval now = (const struct timeval){ 0 };
1122 deque<struct timeval> *events = NULL;
1123 if (i == 0) {
1124 SetStateField(Service::kStateConnected);
1125 now.tv_sec = GetDisconnectsMonitorSeconds() + 1;
1126 events = GetDisconnects();
1127 } else {
1128 SetStateField(Service::kStateAssociating);
1129 now.tv_sec = GetMisconnectsMonitorSeconds() + 1;
1130 events = GetMisconnects();
1131 }
1132 events->push_back((const struct timeval){ 0 });
1133 events->push_back((const struct timeval){ 0 });
1134 EXPECT_CALL(time_, GetTimeMonotonic(_))
1135 .WillOnce(DoAll(SetArgumentPointee<0>(now), Return(0)));
1136 NoteDisconnectEvent();
1137 ASSERT_EQ(1, events->size());
1138 EXPECT_EQ(now.tv_sec, events->front().tv_sec);
1139 }
1140}
1141
1142TEST_F(ServiceTest, NoteDisconnectEventDiscardExcessive) {
1143 EXPECT_FALSE(service_->explicitly_disconnected());
1144 SetStateField(Service::kStateOnline);
1145 static const struct timeval now = (const struct timeval){ 0 };
1146 for (int i = 0; i < 2 * GetMaxDisconnectEventHistory(); i++) {
1147 GetDisconnects()->push_back(now);
1148 }
1149 EXPECT_CALL(time_, GetTimeMonotonic(_))
1150 .WillOnce(DoAll(SetArgumentPointee<0>(now), Return(0)));
1151 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(1);
1152 NoteDisconnectEvent();
1153 EXPECT_EQ(GetMaxDisconnectEventHistory(), GetDisconnects()->size());
1154}
1155
Chris Masone3bd3c8c2011-06-13 08:20:26 -07001156} // namespace shill