blob: 0f910f4aa882ec680c99cc3bb1e6f8a7b001c352 [file] [log] [blame]
Arman Uguray2717a102013-01-29 23:36:06 -08001// Copyright (c) 2013 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"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070034#include "shill/property_store_unittest.h"
Chris Masone6515aab2011-10-12 16:19:09 -070035#include "shill/service_under_test.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070036
Eric Shienbrood9a245532012-03-07 14:20:39 -050037using base::Bind;
38using base::Unretained;
Darin Petkov385b9bc2012-12-03 15:25:05 +010039using std::deque;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070040using std::map;
41using std::string;
42using std::vector;
Darin Petkovba40dd32011-07-11 20:06:39 -070043using testing::_;
mukesh agrawalcf24a242012-05-21 16:46:11 -070044using testing::AnyNumber;
Darin Petkovba40dd32011-07-11 20:06:39 -070045using testing::AtLeast;
Darin Petkov0c65bdd2012-12-05 13:42:41 +010046using testing::DefaultValue;
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_)),
mukesh agrawal43970a22013-02-15 16:00:07 -080068 service2_(new ServiceUnderTest(control_interface(),
69 dispatcher(),
70 metrics(),
71 &mock_manager_)),
Darin Petkovcb0b5662012-12-13 09:59:44 +010072 storage_id_(ServiceUnderTest::kStorageId),
73 power_manager_(new MockPowerManager(NULL, &proxy_factory_)) {
Darin Petkov385b9bc2012-12-03 15:25:05 +010074 service_->time_ = &time_;
Darin Petkov0c65bdd2012-12-05 13:42:41 +010075 DefaultValue<Timestamp>::Set(Timestamp());
Darin Petkov385b9bc2012-12-03 15:25:05 +010076 service_->diagnostics_reporter_ = &diagnostics_reporter_;
Darin Petkovcb0b5662012-12-13 09:59:44 +010077 mock_manager_.running_ = true;
78 mock_manager_.set_power_manager(power_manager_); // Passes ownership.
Chris Masone9d779932011-08-25 16:33:41 -070079 }
Chris Masoneb925cc82011-06-22 15:39:57 -070080
Chris Masone3bd3c8c2011-06-13 08:20:26 -070081 virtual ~ServiceTest() {}
Chris Masoneb925cc82011-06-22 15:39:57 -070082
Eric Shienbrood9a245532012-03-07 14:20:39 -050083 MOCK_METHOD1(TestCallback, void(const Error &error));
84
Chris Masoneb925cc82011-06-22 15:39:57 -070085 protected:
mukesh agrawalcf24a242012-05-21 16:46:11 -070086 typedef scoped_refptr<MockProfile> MockProfileRefPtr;
Eric Shienbrood9a245532012-03-07 14:20:39 -050087
Darin Petkovcb0b5662012-12-13 09:59:44 +010088 class TestProxyFactory : public ProxyFactory {
89 public:
90 TestProxyFactory() {}
91
92 virtual PowerManagerProxyInterface *CreatePowerManagerProxy(
93 PowerManagerProxyDelegate *delegate) {
94 return NULL;
95 }
96
97 private:
98 DISALLOW_COPY_AND_ASSIGN(TestProxyFactory);
99 };
100
Darin Petkov457728b2013-01-09 09:49:08 +0100101 string GetFriendlyName() { return service_->friendly_name(); }
102
Darin Petkovcb0b5662012-12-13 09:59:44 +0100103 void SetManagerRunning(bool running) { mock_manager_.running_ = running; }
104
105 void SetPowerState(PowerManager::SuspendState state) {
106 power_manager_->power_state_ = state;
107 }
108
Darin Petkov385b9bc2012-12-03 15:25:05 +0100109 void SetExplicitlyDisconnected(bool explicitly) {
110 service_->explicitly_disconnected_ = explicitly;
111 }
112
113 void SetStateField(Service::ConnectState state) { service_->state_ = state; }
114
Darin Petkovc8d91e52013-01-21 11:43:47 +0100115 Service::ConnectState GetPreviousState() const {
116 return service_->previous_state_;
117 }
118
Darin Petkov385b9bc2012-12-03 15:25:05 +0100119 void NoteDisconnectEvent() {
120 service_->NoteDisconnectEvent();
121 }
122
Darin Petkov0c65bdd2012-12-05 13:42:41 +0100123 deque<Timestamp> *GetDisconnects() {
124 return &service_->disconnects_;
125 }
126 deque<Timestamp> *GetMisconnects() {
127 return &service_->misconnects_;
128 }
129
130 Timestamp GetTimestamp(int monotonic_seconds, const string &wall_clock) {
131 struct timeval monotonic = { .tv_sec = monotonic_seconds, .tv_usec = 0 };
132 return Timestamp(monotonic, wall_clock);
133 }
134
135 void PushTimestamp(deque<Timestamp> *timestamps,
136 int monotonic_seconds,
137 const string &wall_clock) {
138 timestamps->push_back(GetTimestamp(monotonic_seconds, wall_clock));
139 }
Darin Petkov385b9bc2012-12-03 15:25:05 +0100140
141 int GetDisconnectsMonitorSeconds() {
142 return Service::kDisconnectsMonitorSeconds;
143 }
144
145 int GetMisconnectsMonitorSeconds() {
146 return Service::kMisconnectsMonitorSeconds;
147 }
148
149 int GetReportDisconnectsThreshold() {
150 return Service::kReportDisconnectsThreshold;
151 }
152
153 int GetReportMisconnectsThreshold() {
154 return Service::kReportMisconnectsThreshold;
155 }
156
157 int GetMaxDisconnectEventHistory() {
158 return Service::kMaxDisconnectEventHistory;
159 }
160
Darin Petkov0c65bdd2012-12-05 13:42:41 +0100161 static Strings ExtractWallClockToStrings(const deque<Timestamp> &timestamps) {
162 return Service::ExtractWallClockToStrings(timestamps);
163 }
164
Paul Stewart03dba0b2011-08-22 16:32:45 -0700165 MockManager mock_manager_;
Darin Petkov385b9bc2012-12-03 15:25:05 +0100166 MockDiagnosticsReporter diagnostics_reporter_;
167 MockTime time_;
Paul Stewart03dba0b2011-08-22 16:32:45 -0700168 scoped_refptr<ServiceUnderTest> service_;
mukesh agrawal43970a22013-02-15 16:00:07 -0800169 scoped_refptr<ServiceUnderTest> service2_;
Chris Masone34af2182011-08-22 11:59:36 -0700170 string storage_id_;
Darin Petkovcb0b5662012-12-13 09:59:44 +0100171 TestProxyFactory proxy_factory_;
172 MockPowerManager *power_manager_; // Owned by |mock_manager_|.
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700173};
174
Christopher Wiley0801d192012-09-24 11:57:15 -0700175class AllMockServiceTest : public testing::Test {
176 public:
177 AllMockServiceTest()
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800178 : metrics_(&dispatcher_),
179 manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
Christopher Wiley0801d192012-09-24 11:57:15 -0700180 service_(new ServiceUnderTest(&control_interface_,
181 &dispatcher_,
182 &metrics_,
183 &manager_)) { }
184 virtual ~AllMockServiceTest() {}
185
186 protected:
187 MockControl control_interface_;
188 StrictMock<MockEventDispatcher> dispatcher_;
189 MockGLib glib_;
190 NiceMock<MockMetrics> metrics_;
191 MockManager manager_;
192 scoped_refptr<ServiceUnderTest> service_;
193};
194
Darin Petkovba40dd32011-07-11 20:06:39 -0700195TEST_F(ServiceTest, Constructor) {
196 EXPECT_TRUE(service_->save_credentials_);
197 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400198 EXPECT_EQ(Service::kStateIdle, service_->state());
mukesh agrawalcf24a242012-05-21 16:46:11 -0700199 EXPECT_FALSE(service_->has_ever_connected());
Darin Petkovba40dd32011-07-11 20:06:39 -0700200}
201
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200202TEST_F(ServiceTest, CalculateState) {
203 service_->state_ = Service::kStateConnected;
204 Error error;
205 EXPECT_EQ(flimflam::kStateReady, service_->CalculateState(&error));
206 EXPECT_TRUE(error.IsSuccess());
207}
208
209TEST_F(ServiceTest, CalculateTechnology) {
210 service_->technology_ = Technology::kWifi;
211 Error error;
212 EXPECT_EQ(flimflam::kTypeWifi, service_->CalculateTechnology(&error));
213 EXPECT_TRUE(error.IsSuccess());
214}
215
Chris Masonea8a2c252011-06-27 22:16:30 -0700216TEST_F(ServiceTest, GetProperties) {
217 map<string, ::DBus::Variant> props;
218 Error error(Error::kInvalidProperty, "");
219 {
220 ::DBus::Error dbus_error;
Paul Stewartd215af62012-04-24 23:25:50 -0700221 string expected("true");
mukesh agrawalde29fa82011-09-16 16:16:36 -0700222 service_->mutable_store()->SetStringProperty(flimflam::kCheckPortalProperty,
223 expected,
224 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700225 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700226 ASSERT_FALSE(props.find(flimflam::kCheckPortalProperty) == props.end());
227 EXPECT_EQ(props[flimflam::kCheckPortalProperty].reader().get_string(),
228 expected);
229 }
230 {
231 ::DBus::Error dbus_error;
232 bool expected = true;
Thieu Le284fe792012-01-31 17:53:19 -0800233 service_->set_favorite(true);
mukesh agrawalde29fa82011-09-16 16:16:36 -0700234 service_->mutable_store()->SetBoolProperty(flimflam::kAutoConnectProperty,
235 expected,
236 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700237 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700238 ASSERT_FALSE(props.find(flimflam::kAutoConnectProperty) == props.end());
239 EXPECT_EQ(props[flimflam::kAutoConnectProperty].reader().get_bool(),
240 expected);
241 }
242 {
243 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -0700244 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700245 ASSERT_FALSE(props.find(flimflam::kConnectableProperty) == props.end());
246 EXPECT_EQ(props[flimflam::kConnectableProperty].reader().get_bool(), false);
247 }
248 {
249 ::DBus::Error dbus_error;
250 int32 expected = 127;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700251 service_->mutable_store()->SetInt32Property(flimflam::kPriorityProperty,
252 expected,
253 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700254 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700255 ASSERT_FALSE(props.find(flimflam::kPriorityProperty) == props.end());
256 EXPECT_EQ(props[flimflam::kPriorityProperty].reader().get_int32(),
257 expected);
258 }
Chris Masone95207da2011-06-29 16:50:49 -0700259 {
260 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -0700261 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masone95207da2011-06-29 16:50:49 -0700262 ASSERT_FALSE(props.find(flimflam::kDeviceProperty) == props.end());
Jason Glasgowacdc11f2012-03-30 14:12:22 -0400263 EXPECT_EQ(props[flimflam::kDeviceProperty].reader().get_path(),
Paul Stewart03dba0b2011-08-22 16:32:45 -0700264 string(ServiceUnderTest::kRpcId));
Chris Masone95207da2011-06-29 16:50:49 -0700265 }
Chris Masonea8a2c252011-06-27 22:16:30 -0700266}
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700267
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800268TEST_F(ServiceTest, SetProperty) {
Chris Masonea8a2c252011-06-27 22:16:30 -0700269 {
270 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800271 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
272 flimflam::kSaveCredentialsProperty,
273 PropertyStoreTest::kBoolV,
274 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700275 }
276 {
277 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800278 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
279 flimflam::kPriorityProperty,
280 PropertyStoreTest::kInt32V,
281 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700282 }
283 {
284 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800285 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
286 flimflam::kEAPEAPProperty,
287 PropertyStoreTest::kStringV,
288 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700289 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700290 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
Chris Masonea8a2c252011-06-27 22:16:30 -0700291 {
292 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800293 EXPECT_FALSE(DBusAdaptor::SetProperty(service_->mutable_store(),
294 flimflam::kFavoriteProperty,
295 PropertyStoreTest::kBoolV,
296 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700297 EXPECT_EQ(invalid_args(), error.name());
Chris Masonea8a2c252011-06-27 22:16:30 -0700298 }
Thieu Le284fe792012-01-31 17:53:19 -0800299 {
300 ::DBus::Error error;
301 service_->set_favorite(true);
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800302 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
303 flimflam::kAutoConnectProperty,
304 PropertyStoreTest::kBoolV,
305 &error));
Thieu Le284fe792012-01-31 17:53:19 -0800306 }
307 {
308 ::DBus::Error error;
309 service_->set_favorite(false);
Wade Guthrie4f28e8b2012-04-11 10:52:07 -0700310 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800311 flimflam::kAutoConnectProperty,
312 PropertyStoreTest::kBoolV,
313 &error));
Thieu Le284fe792012-01-31 17:53:19 -0800314 }
Paul Stewart0c438332012-04-11 07:55:27 -0700315 // Ensure that we can perform a trivial set of the Name property (to its
316 // current value) but an attempt to set the property to a different value
317 // fails.
318 {
319 ::DBus::Error error;
320 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
321 flimflam::kNameProperty,
322 DBusAdaptor::StringToVariant(
Darin Petkov457728b2013-01-09 09:49:08 +0100323 GetFriendlyName()),
Paul Stewart0c438332012-04-11 07:55:27 -0700324 &error));
325 }
326 {
327 ::DBus::Error error;
328 EXPECT_FALSE(DBusAdaptor::SetProperty(service_->mutable_store(),
329 flimflam::kNameProperty,
330 PropertyStoreTest::kStringV,
331 &error));
332 EXPECT_EQ(invalid_args(), error.name());
333 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700334}
335
Darin Petkovba40dd32011-07-11 20:06:39 -0700336TEST_F(ServiceTest, Load) {
337 NiceMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700338 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
339 EXPECT_CALL(storage, GetString(storage_id_, _, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700340 .Times(AtLeast(1))
341 .WillRepeatedly(Return(true));
Darin Petkov0debec02013-01-22 10:40:05 +0100342 EXPECT_CALL(storage, GetBool(storage_id_, _, _)).Times(AnyNumber());
343 EXPECT_CALL(storage,
344 GetBool(storage_id_, Service::kStorageSaveCredentials, _));
Chris Masone9d779932011-08-25 16:33:41 -0700345 EXPECT_TRUE(service_->Load(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700346}
347
348TEST_F(ServiceTest, LoadFail) {
349 StrictMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700350 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(false));
Chris Masone9d779932011-08-25 16:33:41 -0700351 EXPECT_FALSE(service_->Load(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700352}
353
354TEST_F(ServiceTest, SaveString) {
355 MockStore storage;
356 static const char kKey[] = "test-key";
357 static const char kData[] = "test-data";
Chris Masone34af2182011-08-22 11:59:36 -0700358 EXPECT_CALL(storage, SetString(storage_id_, kKey, kData))
Darin Petkovba40dd32011-07-11 20:06:39 -0700359 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700360 service_->SaveString(&storage, storage_id_, kKey, kData, false, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700361}
362
363TEST_F(ServiceTest, SaveStringCrypted) {
364 MockStore storage;
365 static const char kKey[] = "test-key";
366 static const char kData[] = "test-data";
Chris Masone34af2182011-08-22 11:59:36 -0700367 EXPECT_CALL(storage, SetCryptedString(storage_id_, kKey, kData))
Darin Petkovba40dd32011-07-11 20:06:39 -0700368 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700369 service_->SaveString(&storage, storage_id_, kKey, kData, true, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700370}
371
372TEST_F(ServiceTest, SaveStringDontSave) {
373 MockStore storage;
374 static const char kKey[] = "test-key";
Chris Masone34af2182011-08-22 11:59:36 -0700375 EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
Darin Petkovba40dd32011-07-11 20:06:39 -0700376 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700377 service_->SaveString(&storage, storage_id_, kKey, "data", false, false);
Darin Petkovba40dd32011-07-11 20:06:39 -0700378}
379
380TEST_F(ServiceTest, SaveStringEmpty) {
381 MockStore storage;
382 static const char kKey[] = "test-key";
Chris Masone34af2182011-08-22 11:59:36 -0700383 EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
Darin Petkovba40dd32011-07-11 20:06:39 -0700384 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700385 service_->SaveString(&storage, storage_id_, kKey, "", true, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700386}
387
388TEST_F(ServiceTest, Save) {
389 NiceMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700390 EXPECT_CALL(storage, SetString(storage_id_, _, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700391 .Times(AtLeast(1))
392 .WillRepeatedly(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700393 EXPECT_CALL(storage, DeleteKey(storage_id_, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700394 .Times(AtLeast(1))
395 .WillRepeatedly(Return(true));
Darin Petkov0debec02013-01-22 10:40:05 +0100396 EXPECT_CALL(storage, SetBool(storage_id_, _, _)).Times(AnyNumber());
397 EXPECT_CALL(storage,
398 SetBool(storage_id_,
399 Service::kStorageSaveCredentials,
400 service_->save_credentials()));
Chris Masone9d779932011-08-25 16:33:41 -0700401 EXPECT_TRUE(service_->Save(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700402}
403
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800404TEST_F(ServiceTest, Unload) {
405 NiceMock<MockStore> storage;
406 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
407 static const string string_value("value");
408 EXPECT_CALL(storage, GetString(storage_id_, _, _))
409 .Times(AtLeast(1))
410 .WillRepeatedly(DoAll(SetArgumentPointee<2>(string_value), Return(true)));
Paul Stewart88769de2012-09-21 13:14:36 -0700411 EXPECT_CALL(storage, GetBool(storage_id_, _, _))
412 .Times(AtLeast(1))
413 .WillRepeatedly(DoAll(SetArgumentPointee<2>(true), Return(true)));
414 EXPECT_FALSE(service_->explicitly_disconnected_);
415 service_->explicitly_disconnected_ = true;
416 EXPECT_FALSE(service_->has_ever_connected_);
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800417 ASSERT_TRUE(service_->Load(&storage));
Paul Stewarte7cce8f2012-09-11 10:56:38 -0700418 // TODO(pstew): Only two string properties in the service are tested as
mukesh agrawalcf24a242012-05-21 16:46:11 -0700419 // a sentinel that properties are being set and reset at the right times.
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800420 // However, since property load/store is essentially a manual process,
421 // it is error prone and should either be exhaustively unit-tested or
422 // a generic framework for registering loaded/stored properties should
423 // be created. crosbug.com/24859
424 EXPECT_EQ(string_value, service_->ui_data_);
Paul Stewarte7cce8f2012-09-11 10:56:38 -0700425 EXPECT_EQ(string_value, service_->guid_);
Paul Stewart88769de2012-09-21 13:14:36 -0700426 EXPECT_FALSE(service_->explicitly_disconnected_);
427 EXPECT_TRUE(service_->has_ever_connected_);
428 service_->explicitly_disconnected_ = true;
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800429 service_->Unload();
430 EXPECT_EQ(string(""), service_->ui_data_);
Paul Stewarte7cce8f2012-09-11 10:56:38 -0700431 EXPECT_EQ(string(""), service_->guid_);
Philipp Neubeckf883a7b2012-09-14 19:52:44 +0200432 EXPECT_FALSE(service_->explicitly_disconnected_);
Paul Stewart88769de2012-09-21 13:14:36 -0700433 EXPECT_FALSE(service_->has_ever_connected_);
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800434}
435
Paul Stewart03dba0b2011-08-22 16:32:45 -0700436TEST_F(ServiceTest, State) {
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400437 EXPECT_EQ(Service::kStateIdle, service_->state());
Darin Petkovc8d91e52013-01-21 11:43:47 +0100438 EXPECT_EQ(Service::kStateIdle, GetPreviousState());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700439 EXPECT_EQ(Service::kFailureUnknown, service_->failure());
Paul Stewartf2d60912012-07-15 08:37:30 -0700440 const string unknown_error(
441 Service::ConnectFailureToString(Service::kFailureUnknown));
442 EXPECT_EQ(unknown_error, service_->error());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700443
mukesh agrawal00917ce2011-11-22 23:56:55 +0000444 ServiceRefPtr service_ref(service_);
mukesh agrawalf2f68a52011-09-01 12:15:48 -0700445
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400446 EXPECT_CALL(*dynamic_cast<ServiceMockAdaptor *>(service_->adaptor_.get()),
mukesh agrawalcf24a242012-05-21 16:46:11 -0700447 EmitStringChanged(flimflam::kStateProperty, _)).Times(7);
Paul Stewartf2d60912012-07-15 08:37:30 -0700448 EXPECT_CALL(*dynamic_cast<ServiceMockAdaptor *>(service_->adaptor_.get()),
449 EmitStringChanged(flimflam::kErrorProperty, _)).Times(4);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700450 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
451 service_->SetState(Service::kStateConnected);
Darin Petkovc8d91e52013-01-21 11:43:47 +0100452 EXPECT_EQ(Service::kStateIdle, GetPreviousState());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700453 // A second state change shouldn't cause another update
454 service_->SetState(Service::kStateConnected);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700455 EXPECT_EQ(Service::kStateConnected, service_->state());
Darin Petkovc8d91e52013-01-21 11:43:47 +0100456 EXPECT_EQ(Service::kStateIdle, GetPreviousState());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700457 EXPECT_EQ(Service::kFailureUnknown, service_->failure());
mukesh agrawalcf24a242012-05-21 16:46:11 -0700458 EXPECT_TRUE(service_->has_ever_connected_);
mukesh agrawal568b5c62012-02-28 14:44:47 -0800459
Paul Stewart03dba0b2011-08-22 16:32:45 -0700460 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
461 service_->SetState(Service::kStateDisconnected);
Darin Petkovc8d91e52013-01-21 11:43:47 +0100462 EXPECT_EQ(Service::kStateConnected, GetPreviousState());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700463
464 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
465 service_->SetFailure(Service::kFailureOutOfRange);
mukesh agrawal568b5c62012-02-28 14:44:47 -0800466 EXPECT_TRUE(service_->IsFailed());
467 EXPECT_GT(service_->failed_time_, 0);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700468 EXPECT_EQ(Service::kStateFailure, service_->state());
469 EXPECT_EQ(Service::kFailureOutOfRange, service_->failure());
Paul Stewartf2d60912012-07-15 08:37:30 -0700470 const string out_of_range_error(
471 Service::ConnectFailureToString(Service::kFailureOutOfRange));
472 EXPECT_EQ(out_of_range_error, service_->error());
mukesh agrawal568b5c62012-02-28 14:44:47 -0800473
474 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
475 service_->SetState(Service::kStateConnected);
476 EXPECT_FALSE(service_->IsFailed());
477 EXPECT_EQ(service_->failed_time_, 0);
Paul Stewartf2d60912012-07-15 08:37:30 -0700478 EXPECT_EQ(unknown_error, service_->error());
mukesh agrawal568b5c62012-02-28 14:44:47 -0800479
480 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
481 service_->SetFailureSilent(Service::kFailurePinMissing);
482 EXPECT_TRUE(service_->IsFailed());
483 EXPECT_GT(service_->failed_time_, 0);
484 EXPECT_EQ(Service::kStateIdle, service_->state());
485 EXPECT_EQ(Service::kFailurePinMissing, service_->failure());
Paul Stewartf2d60912012-07-15 08:37:30 -0700486 const string pin_missing_error(
487 Service::ConnectFailureToString(Service::kFailurePinMissing));
488 EXPECT_EQ(pin_missing_error, service_->error());
mukesh agrawalcf24a242012-05-21 16:46:11 -0700489
490 // If the Service has a Profile, the profile should be saved when
491 // the service enters kStateConnected. (The case where the service
492 // doesn't have a profile is tested above.)
493 MockProfileRefPtr mock_profile(
Thieu Le5133b712013-02-19 14:47:21 -0800494 new MockProfile(control_interface(), metrics(), &mock_manager_));
mukesh agrawalcf24a242012-05-21 16:46:11 -0700495 NiceMock<MockStore> storage;
496 service_->set_profile(mock_profile);
497 service_->has_ever_connected_ = false;
498 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
499 EXPECT_CALL(*mock_profile, GetConstStorage())
500 .WillOnce(Return(&storage));
501 EXPECT_CALL(*mock_profile, UpdateService(service_ref));
502 service_->SetState(Service::kStateConnected);
503 EXPECT_TRUE(service_->has_ever_connected_);
504 service_->set_profile(NULL); // Break reference cycle.
505
506 // Similar to the above, but emulate an emphemeral profile, which
507 // has no storage. We can't update the service in the profile, but
508 // we should not crash.
509 service_->state_ = Service::kStateIdle; // Skips state change logic.
510 service_->set_profile(mock_profile);
511 service_->has_ever_connected_ = false;
512 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
513 EXPECT_CALL(*mock_profile, GetConstStorage()).
514 WillOnce(Return(static_cast<StoreInterface *>(NULL)));
515 service_->SetState(Service::kStateConnected);
516 EXPECT_TRUE(service_->has_ever_connected_);
517 service_->set_profile(NULL); // Break reference cycle.
Paul Stewart03dba0b2011-08-22 16:32:45 -0700518}
519
Darin Petkovb100ae72011-08-24 16:19:45 -0700520TEST_F(ServiceTest, ActivateCellularModem) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500521 ResultCallback callback =
522 Bind(&ServiceTest::TestCallback, Unretained(this));
523 EXPECT_CALL(*this, TestCallback(_)).Times(0);
Darin Petkovb100ae72011-08-24 16:19:45 -0700524 Error error;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500525 service_->ActivateCellularModem("Carrier", &error, callback);
526 EXPECT_TRUE(error.IsFailure());
Darin Petkovb100ae72011-08-24 16:19:45 -0700527}
528
Ben Chan5d924542013-02-14 17:49:08 -0800529TEST_F(ServiceTest, CompleteCellularActivation) {
530 Error error;
531 service_->CompleteCellularActivation(&error);
532 EXPECT_EQ(Error::kNotSupported, error.type());
533}
534
mukesh agrawal00917ce2011-11-22 23:56:55 +0000535TEST_F(ServiceTest, MakeFavorite) {
536 EXPECT_FALSE(service_->favorite());
537 EXPECT_FALSE(service_->auto_connect());
538
539 service_->MakeFavorite();
540 EXPECT_TRUE(service_->favorite());
541 EXPECT_TRUE(service_->auto_connect());
542}
543
544TEST_F(ServiceTest, ReMakeFavorite) {
545 service_->MakeFavorite();
546 EXPECT_TRUE(service_->favorite());
547 EXPECT_TRUE(service_->auto_connect());
548
549 service_->set_auto_connect(false);
550 service_->MakeFavorite();
551 EXPECT_TRUE(service_->favorite());
552 EXPECT_FALSE(service_->auto_connect());
553}
554
mukesh agrawal76d13882012-01-12 15:23:11 -0800555TEST_F(ServiceTest, IsAutoConnectable) {
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100556 const char *reason = NULL;
mukesh agrawal76d13882012-01-12 15:23:11 -0800557 service_->set_connectable(true);
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100558
559 // Services with non-primary connectivity technologies should not auto-connect
560 // when the system is offline.
561 EXPECT_EQ(Technology::kUnknown, service_->technology());
562 EXPECT_CALL(mock_manager_, IsOnline()).WillOnce(Return(false));
563 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
564 EXPECT_STREQ(Service::kAutoConnOffline, reason);
565
566 service_->technology_ = Technology::kEthernet;
mukesh agrawalbf14e942012-03-02 14:36:34 -0800567 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawal76d13882012-01-12 15:23:11 -0800568
mukesh agrawaladb68482012-01-17 16:31:51 -0800569 // We should not auto-connect to a Service that a user has
570 // deliberately disconnected.
571 Error error;
Christopher Wileyabd3b502012-09-26 13:08:52 -0700572 service_->UserInitiatedDisconnect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800573 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
574 EXPECT_STREQ(Service::kAutoConnExplicitDisconnect, reason);
mukesh agrawaladb68482012-01-17 16:31:51 -0800575
576 // But if the Service is reloaded, it is eligible for auto-connect
577 // again.
578 NiceMock<MockStore> storage;
579 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
580 EXPECT_TRUE(service_->Load(&storage));
mukesh agrawalbf14e942012-03-02 14:36:34 -0800581 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800582
583 // A deliberate Connect should also re-enable auto-connect.
Christopher Wileyabd3b502012-09-26 13:08:52 -0700584 service_->UserInitiatedDisconnect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800585 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800586 service_->Connect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800587 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800588
Christopher Wileyabd3b502012-09-26 13:08:52 -0700589 // A non-user initiated Disconnect doesn't change anything.
590 service_->Disconnect(&error);
591 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
592
Christopher Wileya4c61ae2012-10-01 11:04:30 -0700593 // A resume also re-enables auto-connect.
594 service_->UserInitiatedDisconnect(&error);
595 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
596 service_->OnAfterResume();
597 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800598
mukesh agrawal76d13882012-01-12 15:23:11 -0800599 service_->SetState(Service::kStateConnected);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800600 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
601 EXPECT_STREQ(Service::kAutoConnConnected, reason);
mukesh agrawal76d13882012-01-12 15:23:11 -0800602
603 service_->SetState(Service::kStateAssociating);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800604 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
605 EXPECT_STREQ(Service::kAutoConnConnecting, reason);
mukesh agrawal76d13882012-01-12 15:23:11 -0800606}
607
mukesh agrawal03c15ce2012-11-29 17:36:21 -0800608TEST_F(ServiceTest, AutoConnectLogging) {
609 ScopedMockLog log;
610 EXPECT_CALL(log, Log(_, _, _));
611 service_->set_connectable(true);
612
613 ScopeLogger::GetInstance()->EnableScopesByName("+service");
614 ScopeLogger::GetInstance()->set_verbose_level(1);
615 service_->SetState(Service::kStateConnected);
616 EXPECT_CALL(log, Log(-1, _, HasSubstr(Service::kAutoConnConnected)));
617 service_->AutoConnect();
618
619 ScopeLogger::GetInstance()->EnableScopesByName("-service");
620 ScopeLogger::GetInstance()->set_verbose_level(0);
621 EXPECT_CALL(log, Log(logging::LOG_INFO, _,
622 HasSubstr(Service::kAutoConnNotConnectable)));
623 service_->set_connectable(false);
624 service_->AutoConnect();
625}
626
627
Christopher Wiley0801d192012-09-24 11:57:15 -0700628TEST_F(AllMockServiceTest, AutoConnectWithFailures) {
629 const char *reason;
630 service_->set_connectable(true);
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100631 service_->technology_ = Technology::kEthernet;
Christopher Wiley0801d192012-09-24 11:57:15 -0700632 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
633
634 // The very first AutoConnect() doesn't trigger any throttling.
635 EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(0);
636 service_->AutoConnect();
637 Mock::VerifyAndClearExpectations(&dispatcher_);
638 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
639
640 // The second call does trigger some throttling.
641 EXPECT_CALL(dispatcher_, PostDelayedTask(_,
642 Service::kMinAutoConnectCooldownTimeMilliseconds));
643 service_->AutoConnect();
644 Mock::VerifyAndClearExpectations(&dispatcher_);
645 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
646 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
647
648 // Calling AutoConnect() again before the cooldown terminates does not change
649 // the timeout.
650 EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(0);
651 service_->AutoConnect();
652 Mock::VerifyAndClearExpectations(&dispatcher_);
653 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
654 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
655
656 // Once the timeout expires, we can AutoConnect() again.
657 service_->ReEnableAutoConnectTask();
658 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
659
660 // Timeouts increase exponentially.
661 uint64 next_cooldown_time = service_->auto_connect_cooldown_milliseconds_;
662 EXPECT_EQ(next_cooldown_time,
663 Service::kAutoConnectCooldownBackoffFactor *
664 Service::kMinAutoConnectCooldownTimeMilliseconds);
665 while (next_cooldown_time <=
666 Service::kMaxAutoConnectCooldownTimeMilliseconds) {
667 EXPECT_CALL(dispatcher_, PostDelayedTask(_, next_cooldown_time));
668 service_->AutoConnect();
669 Mock::VerifyAndClearExpectations(&dispatcher_);
670 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
671 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
672 service_->ReEnableAutoConnectTask();
673 next_cooldown_time *= Service::kAutoConnectCooldownBackoffFactor;
674 }
675
676 // Once we hit our cap, future timeouts are the same.
677 for (int32 i = 0; i < 2; i++) {
678 EXPECT_CALL(dispatcher_, PostDelayedTask(_,
679 Service::kMaxAutoConnectCooldownTimeMilliseconds));
680 service_->AutoConnect();
681 Mock::VerifyAndClearExpectations(&dispatcher_);
682 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
683 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
684 service_->ReEnableAutoConnectTask();
685 }
686
687 // Connecting successfully resets our cooldown.
688 service_->SetState(Service::kStateConnected);
689 service_->SetState(Service::kStateIdle);
690 reason = "";
691 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
692 EXPECT_STREQ("", reason);
693 EXPECT_EQ(service_->auto_connect_cooldown_milliseconds_, 0);
694
695 // But future AutoConnects behave as before
696 EXPECT_CALL(dispatcher_, PostDelayedTask(_,
697 Service::kMinAutoConnectCooldownTimeMilliseconds)).Times(1);
698 service_->AutoConnect();
699 service_->AutoConnect();
700 Mock::VerifyAndClearExpectations(&dispatcher_);
701 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
702 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
703
704 // Cooldowns are forgotten if we go through a suspend/resume cycle.
705 service_->OnAfterResume();
706 reason = "";
707 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
708 EXPECT_STREQ("", reason);
709}
710
Paul Stewartcb59fed2012-03-21 21:14:46 -0700711TEST_F(ServiceTest, ConfigureBadProperty) {
712 KeyValueStore args;
713 args.SetString("XXXInvalid", "Value");
714 Error error;
715 service_->Configure(args, &error);
716 EXPECT_FALSE(error.IsSuccess());
717}
718
719TEST_F(ServiceTest, ConfigureBoolProperty) {
720 service_->MakeFavorite();
721 service_->set_auto_connect(false);
722 ASSERT_FALSE(service_->auto_connect());
723 KeyValueStore args;
724 args.SetBool(flimflam::kAutoConnectProperty, true);
725 Error error;
726 service_->Configure(args, &error);
727 EXPECT_TRUE(error.IsSuccess());
728 EXPECT_TRUE(service_->auto_connect());
729}
730
731TEST_F(ServiceTest, ConfigureStringProperty) {
732 const string kEAPManagement0 = "management_zero";
733 const string kEAPManagement1 = "management_one";
734 service_->SetEAPKeyManagement(kEAPManagement0);
735 ASSERT_EQ(kEAPManagement0, service_->GetEAPKeyManagement());
736 KeyValueStore args;
737 args.SetString(flimflam::kEapKeyMgmtProperty, kEAPManagement1);
738 Error error;
739 service_->Configure(args, &error);
740 EXPECT_TRUE(error.IsSuccess());
741 EXPECT_EQ(kEAPManagement1, service_->GetEAPKeyManagement());
742}
743
Paul Stewart7a20aa42013-01-17 12:21:41 -0800744TEST_F(ServiceTest, ConfigureIntProperty) {
745 const int kPriority0 = 100;
746 const int kPriority1 = 200;
747 service_->set_priority(kPriority0);
748 ASSERT_EQ(kPriority0, service_->priority());
749 KeyValueStore args;
750 args.SetInt(flimflam::kPriorityProperty, kPriority1);
751 Error error;
752 service_->Configure(args, &error);
753 EXPECT_TRUE(error.IsSuccess());
754 EXPECT_EQ(kPriority1, service_->priority());
755}
756
Paul Stewartcb59fed2012-03-21 21:14:46 -0700757TEST_F(ServiceTest, ConfigureIgnoredProperty) {
758 service_->MakeFavorite();
759 service_->set_auto_connect(false);
760 ASSERT_FALSE(service_->auto_connect());
761 KeyValueStore args;
762 args.SetBool(flimflam::kAutoConnectProperty, true);
763 Error error;
764 service_->IgnoreParameterForConfigure(flimflam::kAutoConnectProperty);
765 service_->Configure(args, &error);
766 EXPECT_TRUE(error.IsSuccess());
767 EXPECT_FALSE(service_->auto_connect());
768}
769
Paul Stewart7a20aa42013-01-17 12:21:41 -0800770TEST_F(ServiceTest, DoPropertiesMatch) {
771 service_->set_auto_connect(false);
772 const string kGUID0 = "guid_zero";
773 const string kGUID1 = "guid_one";
774 service_->set_guid(kGUID0);
775 const uint32 kPriority0 = 100;
776 const uint32 kPriority1 = 200;
777 service_->set_priority(kPriority0);
778
779 {
780 KeyValueStore args;
781 args.SetString(flimflam::kGuidProperty, kGUID0);
782 args.SetBool(flimflam::kAutoConnectProperty, false);
783 args.SetInt(flimflam::kPriorityProperty, kPriority0);
784 EXPECT_TRUE(service_->DoPropertiesMatch(args));
785 }
786 {
787 KeyValueStore args;
788 args.SetString(flimflam::kGuidProperty, kGUID1);
789 args.SetBool(flimflam::kAutoConnectProperty, false);
790 args.SetInt(flimflam::kPriorityProperty, kPriority0);
791 EXPECT_FALSE(service_->DoPropertiesMatch(args));
792 }
793 {
794 KeyValueStore args;
795 args.SetString(flimflam::kGuidProperty, kGUID0);
796 args.SetBool(flimflam::kAutoConnectProperty, true);
797 args.SetInt(flimflam::kPriorityProperty, kPriority0);
798 EXPECT_FALSE(service_->DoPropertiesMatch(args));
799 }
800 {
801 KeyValueStore args;
802 args.SetString(flimflam::kGuidProperty, kGUID0);
803 args.SetBool(flimflam::kAutoConnectProperty, false);
804 args.SetInt(flimflam::kPriorityProperty, kPriority1);
805 EXPECT_FALSE(service_->DoPropertiesMatch(args));
806 }
807}
808
Paul Stewart10ccbb32012-04-26 15:59:30 -0700809TEST_F(ServiceTest, IsRemembered) {
810 ServiceConstRefPtr service_ref(service_);
811 service_->set_profile(NULL);
812 EXPECT_CALL(mock_manager_, IsServiceEphemeral(_)).Times(0);
813 EXPECT_FALSE(service_->IsRemembered());
814
815 scoped_refptr<MockProfile> profile(
Thieu Le5133b712013-02-19 14:47:21 -0800816 new StrictMock<MockProfile>(control_interface(), metrics(), manager()));
Paul Stewart10ccbb32012-04-26 15:59:30 -0700817 service_->set_profile(profile);
818 EXPECT_CALL(mock_manager_, IsServiceEphemeral(service_ref))
819 .WillOnce(Return(true))
820 .WillOnce(Return(false));
821 EXPECT_FALSE(service_->IsRemembered());
822 EXPECT_TRUE(service_->IsRemembered());
823}
824
Paul Stewartdf3c0a82012-11-09 15:54:33 -0800825TEST_F(ServiceTest, IsDependentOn) {
826 EXPECT_FALSE(service_->IsDependentOn(NULL));
827
828 scoped_ptr<MockDeviceInfo> mock_device_info(
829 new NiceMock<MockDeviceInfo>(control_interface(), dispatcher(), metrics(),
830 &mock_manager_));
831 scoped_refptr<MockConnection> mock_connection0(
832 new NiceMock<MockConnection>(mock_device_info.get()));
833 scoped_refptr<MockConnection> mock_connection1(
834 new NiceMock<MockConnection>(mock_device_info.get()));
835
836 service_->connection_ = mock_connection0;
837 EXPECT_CALL(*mock_connection0.get(), GetLowerConnection())
838 .WillRepeatedly(Return(mock_connection1));
839 EXPECT_FALSE(service_->IsDependentOn(NULL));
840
841 scoped_refptr<ServiceUnderTest> service1 =
842 new ServiceUnderTest(control_interface(),
843 dispatcher(),
844 metrics(),
845 &mock_manager_);
846 EXPECT_FALSE(service_->IsDependentOn(service1));
847
848 service1->connection_ = mock_connection0;
849 EXPECT_FALSE(service_->IsDependentOn(service1));
850
851 service1->connection_ = mock_connection1;
852 EXPECT_TRUE(service_->IsDependentOn(service1));
853
854 service_->connection_ = NULL;
855 service1->connection_ = NULL;
856}
857
Paul Stewartff14b022012-04-24 20:06:23 -0700858TEST_F(ServiceTest, OnPropertyChanged) {
859 scoped_refptr<MockProfile> profile(
Thieu Le5133b712013-02-19 14:47:21 -0800860 new StrictMock<MockProfile>(control_interface(), metrics(), manager()));
Paul Stewartff14b022012-04-24 20:06:23 -0700861 service_->set_profile(NULL);
862 // Expect no crash.
863 service_->OnPropertyChanged("");
864
865 // Expect no call to Update if the profile has no storage.
866 service_->set_profile(profile);
867 EXPECT_CALL(*profile, UpdateService(_)).Times(0);
868 EXPECT_CALL(*profile, GetConstStorage())
869 .WillOnce(Return(reinterpret_cast<StoreInterface *>(NULL)));
870 service_->OnPropertyChanged("");
871
872 // Expect call to Update if the profile has storage.
873 EXPECT_CALL(*profile, UpdateService(_)).Times(1);
874 NiceMock<MockStore> storage;
875 EXPECT_CALL(*profile, GetConstStorage()).WillOnce(Return(&storage));
876 service_->OnPropertyChanged("");
877}
878
Paul Stewartd215af62012-04-24 23:25:50 -0700879
880TEST_F(ServiceTest, RecheckPortal) {
881 ServiceRefPtr service_ref(service_);
882 service_->state_ = Service::kStateIdle;
883 EXPECT_CALL(mock_manager_, RecheckPortalOnService(_)).Times(0);
884 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
885
886 service_->state_ = Service::kStatePortal;
887 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
888 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
889
890 service_->state_ = Service::kStateConnected;
891 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
892 service_->OnPropertyChanged(flimflam::kProxyConfigProperty);
893
894 service_->state_ = Service::kStateOnline;
895 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
896 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
897
898 service_->state_ = Service::kStatePortal;
899 EXPECT_CALL(mock_manager_, RecheckPortalOnService(_)).Times(0);
900 service_->OnPropertyChanged(flimflam::kEAPKeyIDProperty);
901}
902
903TEST_F(ServiceTest, SetCheckPortal) {
904 ServiceRefPtr service_ref(service_);
905 {
906 Error error;
907 service_->SetCheckPortal("false", &error);
908 EXPECT_TRUE(error.IsSuccess());
909 EXPECT_EQ(Service::kCheckPortalFalse, service_->check_portal_);
910 }
911 {
912 Error error;
913 service_->SetCheckPortal("true", &error);
914 EXPECT_TRUE(error.IsSuccess());
915 EXPECT_EQ(Service::kCheckPortalTrue, service_->check_portal_);
916 }
917 {
918 Error error;
919 service_->SetCheckPortal("auto", &error);
920 EXPECT_TRUE(error.IsSuccess());
921 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
922 }
923 {
924 Error error;
925 service_->SetCheckPortal("xxx", &error);
926 EXPECT_FALSE(error.IsSuccess());
927 EXPECT_EQ(Error::kInvalidArguments, error.type());
928 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
929 }
930}
931
Arman Uguray2717a102013-01-29 23:36:06 -0800932TEST_F(ServiceTest, SetFriendlyName) {
933 EXPECT_EQ(service_->unique_name_, service_->friendly_name_);
934 ServiceMockAdaptor *adaptor =
935 dynamic_cast<ServiceMockAdaptor *>(service_->adaptor());
936
937 EXPECT_CALL(*adaptor, EmitStringChanged(_, _)).Times(0);
938 service_->SetFriendlyName(service_->unique_name_);
939 EXPECT_EQ(service_->unique_name_, service_->friendly_name_);
940
941 EXPECT_CALL(*adaptor, EmitStringChanged(flimflam::kNameProperty,
942 "Test Name 1"));
943 service_->SetFriendlyName("Test Name 1");
944 EXPECT_EQ("Test Name 1", service_->friendly_name_);
945
946 EXPECT_CALL(*adaptor, EmitStringChanged(_, _)).Times(0);
947 service_->SetFriendlyName("Test Name 1");
948 EXPECT_EQ("Test Name 1", service_->friendly_name_);
949
950 EXPECT_CALL(*adaptor, EmitStringChanged(flimflam::kNameProperty,
951 "Test Name 2"));
952 service_->SetFriendlyName("Test Name 2");
953 EXPECT_EQ("Test Name 2", service_->friendly_name_);
954}
955
Darin Petkovb2ba39f2012-06-06 10:33:43 +0200956TEST_F(ServiceTest, SetConnectable) {
957 EXPECT_FALSE(service_->connectable());
958
959 ServiceMockAdaptor *adaptor =
960 dynamic_cast<ServiceMockAdaptor *>(service_->adaptor());
961
962 EXPECT_CALL(*adaptor, EmitBoolChanged(_, _)).Times(0);
963 EXPECT_CALL(mock_manager_, HasService(_)).Times(0);
964 service_->SetConnectable(false);
965 EXPECT_FALSE(service_->connectable());
966
967 EXPECT_CALL(*adaptor, EmitBoolChanged(flimflam::kConnectableProperty, true));
968 EXPECT_CALL(mock_manager_, HasService(_)).WillOnce(Return(false));
969 EXPECT_CALL(mock_manager_, UpdateService(_)).Times(0);
970 service_->SetConnectable(true);
971 EXPECT_TRUE(service_->connectable());
972
973 EXPECT_CALL(*adaptor, EmitBoolChanged(flimflam::kConnectableProperty, false));
974 EXPECT_CALL(mock_manager_, HasService(_)).WillOnce(Return(true));
975 EXPECT_CALL(mock_manager_, UpdateService(_));
976 service_->SetConnectable(false);
977 EXPECT_FALSE(service_->connectable());
978
979 EXPECT_CALL(*adaptor, EmitBoolChanged(flimflam::kConnectableProperty, true));
980 EXPECT_CALL(mock_manager_, HasService(_)).WillOnce(Return(true));
981 EXPECT_CALL(mock_manager_, UpdateService(_));
982 service_->SetConnectable(true);
983 EXPECT_TRUE(service_->connectable());
984}
985
Paul Stewart9f32d192012-01-30 20:37:50 -0800986// Make sure a property is registered as a write only property
987// by reading and comparing all string properties returned on the store.
988// Subtle: We need to convert the test argument back and forth between
989// string and ::DBus::Variant because this is the parameter type that
990// our supeclass (PropertyStoreTest) is declared with.
991class ReadOnlyServicePropertyTest : public ServiceTest {};
992TEST_P(ReadOnlyServicePropertyTest, PropertyWriteOnly) {
Paul Stewart9f32d192012-01-30 20:37:50 -0800993 string property(GetParam().reader().get_string());
Paul Stewarte6e8e492013-01-17 11:00:50 -0800994 Error error;
995 EXPECT_FALSE(service_->store().GetStringProperty(property, NULL, &error));
996 EXPECT_EQ(Error::kPermissionDenied, error.type());
Paul Stewart9f32d192012-01-30 20:37:50 -0800997}
998
999INSTANTIATE_TEST_CASE_P(
1000 ReadOnlyServicePropertyTestInstance,
1001 ReadOnlyServicePropertyTest,
1002 Values(
1003 DBusAdaptor::StringToVariant(flimflam::kEapPrivateKeyPasswordProperty),
1004 DBusAdaptor::StringToVariant(flimflam::kEapPasswordProperty)));
1005
Paul Stewart10241e32012-04-23 18:15:06 -07001006
1007TEST_F(ServiceTest, GetIPConfigRpcIdentifier) {
1008 {
1009 Error error;
1010 EXPECT_EQ("/", service_->GetIPConfigRpcIdentifier(&error));
1011 EXPECT_EQ(Error::kNotFound, error.type());
1012 }
1013
1014 scoped_ptr<MockDeviceInfo> mock_device_info(
1015 new NiceMock<MockDeviceInfo>(control_interface(), dispatcher(), metrics(),
1016 &mock_manager_));
1017 scoped_refptr<MockConnection> mock_connection(
1018 new NiceMock<MockConnection>(mock_device_info.get()));
1019
1020 service_->connection_ = mock_connection;
1021
1022 {
1023 Error error;
1024 const string empty_string;
1025 EXPECT_CALL(*mock_connection, ipconfig_rpc_identifier())
1026 .WillOnce(ReturnRef(empty_string));
1027 EXPECT_EQ("/", service_->GetIPConfigRpcIdentifier(&error));
1028 EXPECT_EQ(Error::kNotFound, error.type());
1029 }
1030
1031 {
1032 Error error;
1033 const string nonempty_string("/ipconfig/path");
1034 EXPECT_CALL(*mock_connection, ipconfig_rpc_identifier())
1035 .WillOnce(ReturnRef(nonempty_string));
1036 EXPECT_EQ(nonempty_string, service_->GetIPConfigRpcIdentifier(&error));
1037 EXPECT_EQ(Error::kSuccess, error.type());
1038 }
1039
1040 // Assure orderly destruction of the Connection before DeviceInfo.
1041 service_->connection_ = NULL;
1042 mock_connection = NULL;
1043 mock_device_info.reset();
1044}
1045
Paul Stewart81426132012-05-16 10:05:10 -07001046class ServiceWithMockSetEap : public ServiceUnderTest {
1047 public:
1048 ServiceWithMockSetEap(ControlInterface *control_interface,
1049 EventDispatcher *dispatcher,
1050 Metrics *metrics,
1051 Manager *manager)
1052 : ServiceUnderTest(control_interface, dispatcher, metrics, manager),
1053 is_8021x_(false) {}
1054 MOCK_METHOD1(set_eap, void(const EapCredentials &eap));
1055 virtual bool Is8021x() const { return is_8021x_; }
1056 void set_is_8021x(bool is_8021x) { is_8021x_ = is_8021x; }
1057
1058 private:
1059 bool is_8021x_;
1060};
1061
1062TEST_F(ServiceTest, SetEAPCredentialsOverRPC) {
1063 scoped_refptr<ServiceWithMockSetEap> service(
1064 new ServiceWithMockSetEap(control_interface(),
1065 dispatcher(),
1066 metrics(),
1067 &mock_manager_));
1068 string eap_credential_properties[] = {
1069 flimflam::kEAPCertIDProperty,
1070 flimflam::kEAPClientCertProperty,
1071 flimflam::kEAPKeyIDProperty,
1072 flimflam::kEAPPINProperty,
1073 flimflam::kEapCaCertIDProperty,
1074 flimflam::kEapIdentityProperty,
1075 flimflam::kEapPasswordProperty,
1076 flimflam::kEapPrivateKeyProperty
1077 };
1078 string eap_non_credential_properties[] = {
1079 flimflam::kEAPEAPProperty,
1080 flimflam::kEapPhase2AuthProperty,
1081 flimflam::kEapAnonymousIdentityProperty,
1082 flimflam::kEapPrivateKeyPasswordProperty,
Paul Stewart81426132012-05-16 10:05:10 -07001083 flimflam::kEapCaCertNssProperty,
1084 flimflam::kEapUseSystemCAsProperty
1085 };
1086 // While this is not an 802.1x-based service, none of these property
1087 // changes should cause a call to set_eap().
1088 EXPECT_CALL(*service, set_eap(_)).Times(0);
1089 for (size_t i = 0; i < arraysize(eap_credential_properties); ++i)
1090 service->OnPropertyChanged(eap_credential_properties[i]);
1091 for (size_t i = 0; i < arraysize(eap_non_credential_properties); ++i)
1092 service->OnPropertyChanged(eap_non_credential_properties[i]);
Paul Stewartadf79d82012-07-18 16:09:56 -07001093 service->OnPropertyChanged(flimflam::kEapKeyMgmtProperty);
Paul Stewart81426132012-05-16 10:05:10 -07001094
1095 service->set_is_8021x(true);
1096
1097 // When this is an 802.1x-based service, set_eap should be called for
1098 // all credential-carrying properties.
1099 for (size_t i = 0; i < arraysize(eap_credential_properties); ++i) {
1100 EXPECT_CALL(*service, set_eap(_)).Times(1);
1101 service->OnPropertyChanged(eap_credential_properties[i]);
1102 Mock::VerifyAndClearExpectations(service.get());
1103 }
Paul Stewartadf79d82012-07-18 16:09:56 -07001104
1105 // The key management property is a special case. While not strictly
1106 // a credential, it can change which credentials are used. Therefore it
1107 // should also trigger a call to set_eap();
1108 EXPECT_CALL(*service, set_eap(_)).Times(1);
1109 service->OnPropertyChanged(flimflam::kEapKeyMgmtProperty);
1110 Mock::VerifyAndClearExpectations(service.get());
1111
Paul Stewart81426132012-05-16 10:05:10 -07001112 EXPECT_CALL(*service, set_eap(_)).Times(0);
1113 for (size_t i = 0; i < arraysize(eap_non_credential_properties); ++i)
1114 service->OnPropertyChanged(eap_non_credential_properties[i]);
1115}
1116
Paul Stewartbc6e7392012-05-24 07:07:48 -07001117TEST_F(ServiceTest, Certification) {
1118 EXPECT_FALSE(service_->eap_.remote_certification.size());
1119
1120 ScopedMockLog log;
1121 EXPECT_CALL(log, Log(logging::LOG_WARNING, _,
1122 HasSubstr("exceeds our maximum"))).Times(2);
1123 string kSubject("foo");
1124 EXPECT_FALSE(service_->AddEAPCertification(
1125 kSubject, Service::kEAPMaxCertificationElements));
1126 EXPECT_FALSE(service_->AddEAPCertification(
1127 kSubject, Service::kEAPMaxCertificationElements + 1));
1128 EXPECT_FALSE(service_->eap_.remote_certification.size());
1129 Mock::VerifyAndClearExpectations(&log);
1130
1131 EXPECT_CALL(log,
1132 Log(logging::LOG_INFO, _, HasSubstr("Received certification")))
1133 .Times(1);
1134 EXPECT_TRUE(service_->AddEAPCertification(
1135 kSubject, Service::kEAPMaxCertificationElements - 1));
1136 Mock::VerifyAndClearExpectations(&log);
1137 EXPECT_EQ(Service::kEAPMaxCertificationElements,
1138 service_->eap_.remote_certification.size());
1139 for (size_t i = 0; i < Service::kEAPMaxCertificationElements - 1; ++i) {
1140 EXPECT_TRUE(service_->eap_.remote_certification[i].empty());
1141 }
1142 EXPECT_EQ(kSubject, service_->eap_.remote_certification[
1143 Service::kEAPMaxCertificationElements - 1]);
1144
1145 // Re-adding the same name in the same position should not generate a log.
1146 EXPECT_CALL(log, Log(_, _, _)).Times(0);
1147 EXPECT_TRUE(service_->AddEAPCertification(
1148 kSubject, Service::kEAPMaxCertificationElements - 1));
1149
1150 // Replacing the item should generate a log message.
1151 EXPECT_CALL(log,
1152 Log(logging::LOG_INFO, _, HasSubstr("Received certification")))
1153 .Times(1);
1154 EXPECT_TRUE(service_->AddEAPCertification(
1155 kSubject + "x", Service::kEAPMaxCertificationElements - 1));
1156}
1157
Darin Petkovc8d91e52013-01-21 11:43:47 +01001158TEST_F(ServiceTest, NoteDisconnectEventIdle) {
Paul Stewart483e4722012-12-18 10:23:17 -08001159 Timestamp timestamp;
Darin Petkovc8d91e52013-01-21 11:43:47 +01001160 EXPECT_CALL(time_, GetNow()).Times(4).WillRepeatedly((Return(timestamp)));
Darin Petkov385b9bc2012-12-03 15:25:05 +01001161 SetStateField(Service::kStateOnline);
Darin Petkov0857f8e2012-12-21 10:49:17 +01001162 EXPECT_FALSE(service_->HasRecentConnectionIssues());
Darin Petkov385b9bc2012-12-03 15:25:05 +01001163 service_->SetState(Service::kStateIdle);
Darin Petkovc8d91e52013-01-21 11:43:47 +01001164 // The transition Online->Idle is not an event.
Darin Petkov0857f8e2012-12-21 10:49:17 +01001165 EXPECT_FALSE(service_->HasRecentConnectionIssues());
Darin Petkovc8d91e52013-01-21 11:43:47 +01001166 service_->SetState(Service::kStateFailure);
1167 // The transition Online->Idle->Failure is a connection drop.
1168 EXPECT_TRUE(service_->HasRecentConnectionIssues());
Darin Petkov0857f8e2012-12-21 10:49:17 +01001169}
1170
1171TEST_F(ServiceTest, NoteDisconnectEventOnSetStateFailure) {
1172 Timestamp timestamp;
1173 EXPECT_CALL(time_, GetNow()).Times(3).WillRepeatedly((Return(timestamp)));
1174 SetStateField(Service::kStateOnline);
1175 EXPECT_FALSE(service_->HasRecentConnectionIssues());
1176 service_->SetState(Service::kStateFailure);
1177 EXPECT_TRUE(service_->HasRecentConnectionIssues());
1178}
1179
1180TEST_F(ServiceTest, NoteDisconnectEventOnSetFailureSilent) {
1181 Timestamp timestamp;
1182 EXPECT_CALL(time_, GetNow()).Times(3).WillRepeatedly((Return(timestamp)));
1183 SetStateField(Service::kStateConfiguring);
1184 EXPECT_FALSE(service_->HasRecentConnectionIssues());
1185 service_->SetFailureSilent(Service::kFailureEAPAuthentication);
Paul Stewart483e4722012-12-18 10:23:17 -08001186 EXPECT_TRUE(service_->HasRecentConnectionIssues());
Darin Petkov385b9bc2012-12-03 15:25:05 +01001187}
1188
1189TEST_F(ServiceTest, NoteDisconnectEventNonEvent) {
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001190 EXPECT_CALL(time_, GetNow()).Times(0);
Darin Petkov385b9bc2012-12-03 15:25:05 +01001191 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(0);
1192
1193 // Explicit disconnect is a non-event.
1194 SetStateField(Service::kStateOnline);
1195 SetExplicitlyDisconnected(true);
1196 NoteDisconnectEvent();
1197 EXPECT_TRUE(GetDisconnects()->empty());
1198 EXPECT_TRUE(GetMisconnects()->empty());
1199
1200 // Failure to idle transition is a non-event.
1201 SetStateField(Service::kStateFailure);
1202 SetExplicitlyDisconnected(false);
1203 NoteDisconnectEvent();
1204 EXPECT_TRUE(GetDisconnects()->empty());
1205 EXPECT_TRUE(GetMisconnects()->empty());
Darin Petkovcb0b5662012-12-13 09:59:44 +01001206
1207 // Disconnect while manager is stopped is a non-event.
1208 SetStateField(Service::kStateOnline);
1209 SetManagerRunning(false);
1210 NoteDisconnectEvent();
1211 EXPECT_TRUE(GetDisconnects()->empty());
1212 EXPECT_TRUE(GetMisconnects()->empty());
1213
1214 // Disconnect while suspending is a non-event.
1215 SetManagerRunning(true);
1216 SetPowerState(PowerManager::kSuspending);
1217 NoteDisconnectEvent();
1218 EXPECT_TRUE(GetDisconnects()->empty());
1219 EXPECT_TRUE(GetMisconnects()->empty());
Darin Petkov385b9bc2012-12-03 15:25:05 +01001220}
1221
1222TEST_F(ServiceTest, NoteDisconnectEventDisconnectOnce) {
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001223 const int kNow = 5;
Darin Petkov385b9bc2012-12-03 15:25:05 +01001224 EXPECT_FALSE(service_->explicitly_disconnected());
1225 SetStateField(Service::kStateOnline);
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001226 EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(kNow, "")));
Darin Petkov385b9bc2012-12-03 15:25:05 +01001227 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(0);
1228 NoteDisconnectEvent();
1229 ASSERT_EQ(1, GetDisconnects()->size());
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001230 EXPECT_EQ(kNow, GetDisconnects()->front().monotonic.tv_sec);
Darin Petkov385b9bc2012-12-03 15:25:05 +01001231 EXPECT_TRUE(GetMisconnects()->empty());
Paul Stewart483e4722012-12-18 10:23:17 -08001232
1233 Mock::VerifyAndClearExpectations(&time_);
1234 EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(
1235 kNow + GetDisconnectsMonitorSeconds() - 1, "")));
1236 EXPECT_TRUE(service_->HasRecentConnectionIssues());
1237 ASSERT_EQ(1, GetDisconnects()->size());
1238
1239 Mock::VerifyAndClearExpectations(&time_);
1240 EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(
1241 kNow + GetDisconnectsMonitorSeconds(), "")));
1242 EXPECT_FALSE(service_->HasRecentConnectionIssues());
1243 ASSERT_TRUE(GetDisconnects()->empty());
Darin Petkov385b9bc2012-12-03 15:25:05 +01001244}
1245
1246TEST_F(ServiceTest, NoteDisconnectEventDisconnectThreshold) {
1247 EXPECT_FALSE(service_->explicitly_disconnected());
1248 SetStateField(Service::kStateOnline);
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001249 const int kNow = 6;
Darin Petkov385b9bc2012-12-03 15:25:05 +01001250 for (int i = 0; i < GetReportDisconnectsThreshold() - 1; i++) {
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001251 PushTimestamp(GetDisconnects(), kNow, "");
Darin Petkov385b9bc2012-12-03 15:25:05 +01001252 }
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001253 EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(kNow, "")));
Darin Petkov385b9bc2012-12-03 15:25:05 +01001254 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(1);
1255 NoteDisconnectEvent();
1256 EXPECT_EQ(GetReportDisconnectsThreshold(), GetDisconnects()->size());
1257}
1258
1259TEST_F(ServiceTest, NoteDisconnectEventMisconnectOnce) {
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001260 const int kNow = 7;
Darin Petkov385b9bc2012-12-03 15:25:05 +01001261 EXPECT_FALSE(service_->explicitly_disconnected());
1262 SetStateField(Service::kStateConfiguring);
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001263 EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(kNow, "")));
Darin Petkov385b9bc2012-12-03 15:25:05 +01001264 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(0);
1265 NoteDisconnectEvent();
1266 EXPECT_TRUE(GetDisconnects()->empty());
1267 ASSERT_EQ(1, GetMisconnects()->size());
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001268 EXPECT_EQ(kNow, GetMisconnects()->front().monotonic.tv_sec);
Paul Stewart483e4722012-12-18 10:23:17 -08001269
1270 Mock::VerifyAndClearExpectations(&time_);
1271 EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(
1272 kNow + GetMisconnectsMonitorSeconds() - 1, "")));
1273 EXPECT_TRUE(service_->HasRecentConnectionIssues());
1274 ASSERT_EQ(1, GetMisconnects()->size());
1275
1276 Mock::VerifyAndClearExpectations(&time_);
1277 EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(
1278 kNow + GetMisconnectsMonitorSeconds(), "")));
1279 EXPECT_FALSE(service_->HasRecentConnectionIssues());
1280 ASSERT_TRUE(GetMisconnects()->empty());
Darin Petkov385b9bc2012-12-03 15:25:05 +01001281}
1282
1283TEST_F(ServiceTest, NoteDisconnectEventMisconnectThreshold) {
1284 EXPECT_FALSE(service_->explicitly_disconnected());
1285 SetStateField(Service::kStateConfiguring);
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001286 const int kNow = 8;
Darin Petkov385b9bc2012-12-03 15:25:05 +01001287 for (int i = 0; i < GetReportMisconnectsThreshold() - 1; i++) {
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001288 PushTimestamp(GetMisconnects(), kNow, "");
Darin Petkov385b9bc2012-12-03 15:25:05 +01001289 }
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001290 EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(kNow, "")));
Darin Petkov385b9bc2012-12-03 15:25:05 +01001291 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(1);
1292 NoteDisconnectEvent();
1293 EXPECT_EQ(GetReportMisconnectsThreshold(), GetMisconnects()->size());
1294}
1295
1296TEST_F(ServiceTest, NoteDisconnectEventDiscardOld) {
1297 EXPECT_FALSE(service_->explicitly_disconnected());
1298 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(0);
1299 for (int i = 0; i < 2; i++) {
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001300 int now = 0;
1301 deque<Timestamp> *events = NULL;
Darin Petkov385b9bc2012-12-03 15:25:05 +01001302 if (i == 0) {
1303 SetStateField(Service::kStateConnected);
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001304 now = GetDisconnectsMonitorSeconds() + 1;
Darin Petkov385b9bc2012-12-03 15:25:05 +01001305 events = GetDisconnects();
1306 } else {
1307 SetStateField(Service::kStateAssociating);
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001308 now = GetMisconnectsMonitorSeconds() + 1;
Darin Petkov385b9bc2012-12-03 15:25:05 +01001309 events = GetMisconnects();
1310 }
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001311 PushTimestamp(events, 0, "");
1312 PushTimestamp(events, 0, "");
1313 EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(now, "")));
Darin Petkov385b9bc2012-12-03 15:25:05 +01001314 NoteDisconnectEvent();
1315 ASSERT_EQ(1, events->size());
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001316 EXPECT_EQ(now, events->front().monotonic.tv_sec);
Darin Petkov385b9bc2012-12-03 15:25:05 +01001317 }
1318}
1319
1320TEST_F(ServiceTest, NoteDisconnectEventDiscardExcessive) {
1321 EXPECT_FALSE(service_->explicitly_disconnected());
1322 SetStateField(Service::kStateOnline);
Darin Petkov385b9bc2012-12-03 15:25:05 +01001323 for (int i = 0; i < 2 * GetMaxDisconnectEventHistory(); i++) {
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001324 PushTimestamp(GetDisconnects(), 0, "");
Darin Petkov385b9bc2012-12-03 15:25:05 +01001325 }
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001326 EXPECT_CALL(time_, GetNow()).WillOnce(Return(Timestamp()));
Darin Petkov385b9bc2012-12-03 15:25:05 +01001327 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(1);
1328 NoteDisconnectEvent();
1329 EXPECT_EQ(GetMaxDisconnectEventHistory(), GetDisconnects()->size());
1330}
1331
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001332TEST_F(ServiceTest, ConvertTimestampsToStrings) {
1333 EXPECT_TRUE(ExtractWallClockToStrings(deque<Timestamp>()).empty());
1334
1335 const Timestamp kValues[] = {
Darin Petkov0857f8e2012-12-21 10:49:17 +01001336 GetTimestamp(123, "2012-12-09T12:41:22.123456+0100"),
1337 GetTimestamp(234, "2012-12-31T23:59:59.012345+0100")
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001338 };
1339 Strings strings =
1340 ExtractWallClockToStrings(
1341 deque<Timestamp>(kValues, kValues + arraysize(kValues)));
1342 EXPECT_GT(arraysize(kValues), 0);
1343 ASSERT_EQ(arraysize(kValues), strings.size());
1344 for (size_t i = 0; i < arraysize(kValues); i++) {
1345 EXPECT_EQ(kValues[i].wall_clock, strings[i]);
1346 }
1347}
1348
1349TEST_F(ServiceTest, DiagnosticsProperties) {
Darin Petkov0857f8e2012-12-21 10:49:17 +01001350 const string kWallClock0 = "2012-12-09T12:41:22.234567-0800";
1351 const string kWallClock1 = "2012-12-31T23:59:59.345678-0800";
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001352 Strings values;
1353
1354 PushTimestamp(GetDisconnects(), 0, kWallClock0);
Paul Stewarte6e8e492013-01-17 11:00:50 -08001355 Error unused_error;
1356 ASSERT_TRUE(service_->store().GetStringsProperty(
1357 kDiagnosticsDisconnectsProperty, &values, &unused_error));
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001358 ASSERT_EQ(1, values.size());
1359 EXPECT_EQ(kWallClock0, values[0]);
1360
1361 PushTimestamp(GetMisconnects(), 0, kWallClock1);
Paul Stewarte6e8e492013-01-17 11:00:50 -08001362 ASSERT_TRUE(service_->store().GetStringsProperty(
1363 kDiagnosticsMisconnectsProperty, &values, &unused_error));
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001364 ASSERT_EQ(1, values.size());
1365 EXPECT_EQ(kWallClock1, values[0]);
1366}
1367
mukesh agrawal43970a22013-02-15 16:00:07 -08001368TEST_F(ServiceTest, SecurityLevel) {
1369 // Encrypted is better than not.
1370 service_->SetSecurity(Service::kCryptoNone, false, false);
1371 service2_->SetSecurity(Service::kCryptoRc4, false, false);
1372 EXPECT_GT(service2_->SecurityLevel(), service_->SecurityLevel());
1373
1374 // AES encryption is better than RC4 encryption.
1375 service_->SetSecurity(Service::kCryptoRc4, false, false);
1376 service2_->SetSecurity(Service::kCryptoAes, false, false);
1377 EXPECT_GT(service2_->SecurityLevel(), service_->SecurityLevel());
1378
1379 // Crypto algorithm is more important than key rotation.
1380 service_->SetSecurity(Service::kCryptoNone, true, false);
1381 service2_->SetSecurity(Service::kCryptoAes, false, false);
1382 EXPECT_GT(service2_->SecurityLevel(), service_->SecurityLevel());
1383
1384 // Encrypted-but-unauthenticated is better than clear-but-authenticated.
1385 service_->SetSecurity(Service::kCryptoNone, false, true);
1386 service2_->SetSecurity(Service::kCryptoAes, false, false);
1387 EXPECT_GT(service2_->SecurityLevel(), service_->SecurityLevel());
1388
1389 // For same encryption, prefer key rotation.
1390 service_->SetSecurity(Service::kCryptoRc4, false, false);
1391 service2_->SetSecurity(Service::kCryptoRc4, true, false);
1392 EXPECT_GT(service2_->SecurityLevel(), service_->SecurityLevel());
1393
1394 // For same encryption, prefer authenticated AP.
1395 service_->SetSecurity(Service::kCryptoRc4, false, false);
1396 service2_->SetSecurity(Service::kCryptoRc4, false, true);
1397 EXPECT_GT(service2_->SecurityLevel(), service_->SecurityLevel());
1398}
1399
Chris Masone3bd3c8c2011-06-13 08:20:26 -07001400} // namespace shill