blob: f0dd01a3a7800313c7d38e178c20c0d4e4e7026b [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"
Paul Stewartc43cbbe2013-04-11 06:29:30 -070026#include "shill/mock_eap_credentials.h"
Christopher Wiley0801d192012-09-24 11:57:15 -070027#include "shill/mock_event_dispatcher.h"
Paul Stewartbc6e7392012-05-24 07:07:48 -070028#include "shill/mock_log.h"
Paul Stewart03dba0b2011-08-22 16:32:45 -070029#include "shill/mock_manager.h"
Darin Petkovcb0b5662012-12-13 09:59:44 +010030#include "shill/mock_power_manager.h"
Paul Stewartff14b022012-04-24 20:06:23 -070031#include "shill/mock_profile.h"
Darin Petkovcb0b5662012-12-13 09:59:44 +010032#include "shill/mock_proxy_factory.h"
Darin Petkovba40dd32011-07-11 20:06:39 -070033#include "shill/mock_store.h"
Darin Petkov385b9bc2012-12-03 15:25:05 +010034#include "shill/mock_time.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070035#include "shill/property_store_unittest.h"
mukesh agrawalcbfb34e2013-04-17 19:33:25 -070036#include "shill/service_property_change_test.h"
Chris Masone6515aab2011-10-12 16:19:09 -070037#include "shill/service_under_test.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070038
Eric Shienbrood9a245532012-03-07 14:20:39 -050039using base::Bind;
40using base::Unretained;
Darin Petkov385b9bc2012-12-03 15:25:05 +010041using std::deque;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070042using std::map;
43using std::string;
44using std::vector;
Darin Petkovba40dd32011-07-11 20:06:39 -070045using testing::_;
mukesh agrawalcf24a242012-05-21 16:46:11 -070046using testing::AnyNumber;
Darin Petkovba40dd32011-07-11 20:06:39 -070047using testing::AtLeast;
Darin Petkov0c65bdd2012-12-05 13:42:41 +010048using testing::DefaultValue;
Paul Stewartd8ad3c42012-01-09 12:39:38 -080049using testing::DoAll;
Paul Stewartbc6e7392012-05-24 07:07:48 -070050using testing::HasSubstr;
Paul Stewart81426132012-05-16 10:05:10 -070051using testing::Mock;
Darin Petkovba40dd32011-07-11 20:06:39 -070052using testing::NiceMock;
53using testing::Return;
Paul Stewart10241e32012-04-23 18:15:06 -070054using testing::ReturnRef;
Darin Petkovba40dd32011-07-11 20:06:39 -070055using testing::StrictMock;
Paul Stewartd8ad3c42012-01-09 12:39:38 -080056using testing::SetArgumentPointee;
Darin Petkovba40dd32011-07-11 20:06:39 -070057using testing::Test;
Paul Stewart9f32d192012-01-30 20:37:50 -080058using testing::Values;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070059
60namespace shill {
61
62class ServiceTest : public PropertyStoreTest {
63 public:
Chris Masoneb925cc82011-06-22 15:39:57 -070064 ServiceTest()
Thieu Le3426c8f2012-01-11 17:35:11 -080065 : mock_manager_(control_interface(), dispatcher(), metrics(), glib()),
Chris Masone2176a882011-09-14 22:29:15 -070066 service_(new ServiceUnderTest(control_interface(),
67 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -080068 metrics(),
Paul Stewart03dba0b2011-08-22 16:32:45 -070069 &mock_manager_)),
mukesh agrawal43970a22013-02-15 16:00:07 -080070 service2_(new ServiceUnderTest(control_interface(),
71 dispatcher(),
72 metrics(),
73 &mock_manager_)),
Darin Petkovcb0b5662012-12-13 09:59:44 +010074 storage_id_(ServiceUnderTest::kStorageId),
Paul Stewartc43cbbe2013-04-11 06:29:30 -070075 power_manager_(new MockPowerManager(NULL, &proxy_factory_)),
76 eap_(new MockEapCredentials()) {
Darin Petkov385b9bc2012-12-03 15:25:05 +010077 service_->time_ = &time_;
Darin Petkov0c65bdd2012-12-05 13:42:41 +010078 DefaultValue<Timestamp>::Set(Timestamp());
Darin Petkov385b9bc2012-12-03 15:25:05 +010079 service_->diagnostics_reporter_ = &diagnostics_reporter_;
Paul Stewartc43cbbe2013-04-11 06:29:30 -070080 service_->eap_.reset(eap_); // Passes ownership.
Darin Petkovcb0b5662012-12-13 09:59:44 +010081 mock_manager_.running_ = true;
82 mock_manager_.set_power_manager(power_manager_); // Passes ownership.
Chris Masone9d779932011-08-25 16:33:41 -070083 }
Chris Masoneb925cc82011-06-22 15:39:57 -070084
Chris Masone3bd3c8c2011-06-13 08:20:26 -070085 virtual ~ServiceTest() {}
Chris Masoneb925cc82011-06-22 15:39:57 -070086
Eric Shienbrood9a245532012-03-07 14:20:39 -050087 MOCK_METHOD1(TestCallback, void(const Error &error));
88
Chris Masoneb925cc82011-06-22 15:39:57 -070089 protected:
mukesh agrawalcf24a242012-05-21 16:46:11 -070090 typedef scoped_refptr<MockProfile> MockProfileRefPtr;
Eric Shienbrood9a245532012-03-07 14:20:39 -050091
Darin Petkovcb0b5662012-12-13 09:59:44 +010092 class TestProxyFactory : public ProxyFactory {
93 public:
94 TestProxyFactory() {}
95
96 virtual PowerManagerProxyInterface *CreatePowerManagerProxy(
97 PowerManagerProxyDelegate *delegate) {
98 return NULL;
99 }
100
101 private:
102 DISALLOW_COPY_AND_ASSIGN(TestProxyFactory);
103 };
104
Darin Petkovaba89322013-03-11 14:48:22 +0100105 ServiceMockAdaptor *GetAdaptor() {
106 return dynamic_cast<ServiceMockAdaptor *>(service_->adaptor());
107 }
108
Darin Petkov457728b2013-01-09 09:49:08 +0100109 string GetFriendlyName() { return service_->friendly_name(); }
110
Darin Petkovcb0b5662012-12-13 09:59:44 +0100111 void SetManagerRunning(bool running) { mock_manager_.running_ = running; }
112
113 void SetPowerState(PowerManager::SuspendState state) {
114 power_manager_->power_state_ = state;
115 }
116
Darin Petkov385b9bc2012-12-03 15:25:05 +0100117 void SetExplicitlyDisconnected(bool explicitly) {
118 service_->explicitly_disconnected_ = explicitly;
119 }
120
121 void SetStateField(Service::ConnectState state) { service_->state_ = state; }
122
Darin Petkovc8d91e52013-01-21 11:43:47 +0100123 Service::ConnectState GetPreviousState() const {
124 return service_->previous_state_;
125 }
126
Darin Petkov385b9bc2012-12-03 15:25:05 +0100127 void NoteDisconnectEvent() {
128 service_->NoteDisconnectEvent();
129 }
130
Darin Petkov0c65bdd2012-12-05 13:42:41 +0100131 deque<Timestamp> *GetDisconnects() {
132 return &service_->disconnects_;
133 }
134 deque<Timestamp> *GetMisconnects() {
135 return &service_->misconnects_;
136 }
137
138 Timestamp GetTimestamp(int monotonic_seconds, const string &wall_clock) {
139 struct timeval monotonic = { .tv_sec = monotonic_seconds, .tv_usec = 0 };
140 return Timestamp(monotonic, wall_clock);
141 }
142
143 void PushTimestamp(deque<Timestamp> *timestamps,
144 int monotonic_seconds,
145 const string &wall_clock) {
146 timestamps->push_back(GetTimestamp(monotonic_seconds, wall_clock));
147 }
Darin Petkov385b9bc2012-12-03 15:25:05 +0100148
149 int GetDisconnectsMonitorSeconds() {
150 return Service::kDisconnectsMonitorSeconds;
151 }
152
153 int GetMisconnectsMonitorSeconds() {
154 return Service::kMisconnectsMonitorSeconds;
155 }
156
157 int GetReportDisconnectsThreshold() {
158 return Service::kReportDisconnectsThreshold;
159 }
160
161 int GetReportMisconnectsThreshold() {
162 return Service::kReportMisconnectsThreshold;
163 }
164
165 int GetMaxDisconnectEventHistory() {
166 return Service::kMaxDisconnectEventHistory;
167 }
168
Darin Petkov0c65bdd2012-12-05 13:42:41 +0100169 static Strings ExtractWallClockToStrings(const deque<Timestamp> &timestamps) {
170 return Service::ExtractWallClockToStrings(timestamps);
171 }
172
Darin Petkov36d962d2013-03-25 13:03:14 +0100173 bool GetAutoConnect(Error *error) {
174 return service_->GetAutoConnect(error);
175 }
176
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700177 bool SetAutoConnectFull(bool connect, Error *error) {
178 return service_->SetAutoConnectFull(connect, error);
Darin Petkov36d962d2013-03-25 13:03:14 +0100179 }
180
Paul Stewart03dba0b2011-08-22 16:32:45 -0700181 MockManager mock_manager_;
Darin Petkov385b9bc2012-12-03 15:25:05 +0100182 MockDiagnosticsReporter diagnostics_reporter_;
183 MockTime time_;
Paul Stewart03dba0b2011-08-22 16:32:45 -0700184 scoped_refptr<ServiceUnderTest> service_;
mukesh agrawal43970a22013-02-15 16:00:07 -0800185 scoped_refptr<ServiceUnderTest> service2_;
Chris Masone34af2182011-08-22 11:59:36 -0700186 string storage_id_;
Darin Petkovcb0b5662012-12-13 09:59:44 +0100187 TestProxyFactory proxy_factory_;
188 MockPowerManager *power_manager_; // Owned by |mock_manager_|.
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700189 MockEapCredentials *eap_; // Owned by |service_|.
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700190};
191
Christopher Wiley0801d192012-09-24 11:57:15 -0700192class AllMockServiceTest : public testing::Test {
193 public:
194 AllMockServiceTest()
Thieu Le6c1e3bb2013-02-06 15:20:35 -0800195 : metrics_(&dispatcher_),
196 manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
Christopher Wiley0801d192012-09-24 11:57:15 -0700197 service_(new ServiceUnderTest(&control_interface_,
198 &dispatcher_,
199 &metrics_,
200 &manager_)) { }
201 virtual ~AllMockServiceTest() {}
202
203 protected:
204 MockControl control_interface_;
205 StrictMock<MockEventDispatcher> dispatcher_;
206 MockGLib glib_;
207 NiceMock<MockMetrics> metrics_;
208 MockManager manager_;
209 scoped_refptr<ServiceUnderTest> service_;
210};
211
Darin Petkovba40dd32011-07-11 20:06:39 -0700212TEST_F(ServiceTest, Constructor) {
213 EXPECT_TRUE(service_->save_credentials_);
214 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400215 EXPECT_EQ(Service::kStateIdle, service_->state());
mukesh agrawalcf24a242012-05-21 16:46:11 -0700216 EXPECT_FALSE(service_->has_ever_connected());
Darin Petkovba40dd32011-07-11 20:06:39 -0700217}
218
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200219TEST_F(ServiceTest, CalculateState) {
220 service_->state_ = Service::kStateConnected;
221 Error error;
222 EXPECT_EQ(flimflam::kStateReady, service_->CalculateState(&error));
223 EXPECT_TRUE(error.IsSuccess());
224}
225
226TEST_F(ServiceTest, CalculateTechnology) {
227 service_->technology_ = Technology::kWifi;
228 Error error;
229 EXPECT_EQ(flimflam::kTypeWifi, service_->CalculateTechnology(&error));
230 EXPECT_TRUE(error.IsSuccess());
231}
232
Chris Masonea8a2c252011-06-27 22:16:30 -0700233TEST_F(ServiceTest, GetProperties) {
234 map<string, ::DBus::Variant> props;
235 Error error(Error::kInvalidProperty, "");
236 {
237 ::DBus::Error dbus_error;
Paul Stewartd215af62012-04-24 23:25:50 -0700238 string expected("true");
mukesh agrawalde29fa82011-09-16 16:16:36 -0700239 service_->mutable_store()->SetStringProperty(flimflam::kCheckPortalProperty,
240 expected,
241 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700242 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700243 ASSERT_FALSE(props.find(flimflam::kCheckPortalProperty) == props.end());
244 EXPECT_EQ(props[flimflam::kCheckPortalProperty].reader().get_string(),
245 expected);
246 }
247 {
248 ::DBus::Error dbus_error;
249 bool expected = true;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700250 service_->mutable_store()->SetBoolProperty(flimflam::kAutoConnectProperty,
251 expected,
252 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700253 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700254 ASSERT_FALSE(props.find(flimflam::kAutoConnectProperty) == props.end());
255 EXPECT_EQ(props[flimflam::kAutoConnectProperty].reader().get_bool(),
256 expected);
257 }
258 {
259 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -0700260 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700261 ASSERT_FALSE(props.find(flimflam::kConnectableProperty) == props.end());
262 EXPECT_EQ(props[flimflam::kConnectableProperty].reader().get_bool(), false);
263 }
264 {
265 ::DBus::Error dbus_error;
266 int32 expected = 127;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700267 service_->mutable_store()->SetInt32Property(flimflam::kPriorityProperty,
268 expected,
269 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700270 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700271 ASSERT_FALSE(props.find(flimflam::kPriorityProperty) == props.end());
272 EXPECT_EQ(props[flimflam::kPriorityProperty].reader().get_int32(),
273 expected);
274 }
Chris Masone95207da2011-06-29 16:50:49 -0700275 {
276 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -0700277 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masone95207da2011-06-29 16:50:49 -0700278 ASSERT_FALSE(props.find(flimflam::kDeviceProperty) == props.end());
Jason Glasgowacdc11f2012-03-30 14:12:22 -0400279 EXPECT_EQ(props[flimflam::kDeviceProperty].reader().get_path(),
Paul Stewart03dba0b2011-08-22 16:32:45 -0700280 string(ServiceUnderTest::kRpcId));
Chris Masone95207da2011-06-29 16:50:49 -0700281 }
Chris Masonea8a2c252011-06-27 22:16:30 -0700282}
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700283
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800284TEST_F(ServiceTest, SetProperty) {
Chris Masonea8a2c252011-06-27 22:16:30 -0700285 {
286 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800287 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
288 flimflam::kSaveCredentialsProperty,
289 PropertyStoreTest::kBoolV,
290 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700291 }
292 {
293 ::DBus::Error error;
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700294 ::DBus::Variant priority;
295 priority.writer().append_int32(1);
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800296 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
297 flimflam::kPriorityProperty,
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700298 priority,
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800299 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700300 }
301 {
302 ::DBus::Error error;
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700303 ::DBus::Variant guid;
304 guid.writer().append_string("not default");
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800305 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700306 flimflam::kGuidProperty,
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700307 guid,
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700308 &error));
309 }
310 // Ensure that EAP properties cannot be set on services with no EAP
311 // credentials. Use service2_ here since we're have some code in
312 // ServiceTest::SetUp() that fiddles with service_->eap_.
313 {
314 ::DBus::Error error;
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700315 ::DBus::Variant eap;
316 eap.writer().append_string("eap eep eip!");
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700317 EXPECT_FALSE(DBusAdaptor::SetProperty(service2_->mutable_store(),
318 flimflam::kEAPEAPProperty,
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700319 eap,
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700320 &error));
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700321 ASSERT_TRUE(error.is_set()); // name() may be invalid otherwise
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700322 EXPECT_EQ(invalid_prop(), error.name());
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700323 // Now plumb in eap credentials, and try again.
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700324 service2_->SetEapCredentials(new EapCredentials());
325 EXPECT_TRUE(DBusAdaptor::SetProperty(service2_->mutable_store(),
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800326 flimflam::kEAPEAPProperty,
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700327 eap,
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800328 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700329 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700330 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
Chris Masonea8a2c252011-06-27 22:16:30 -0700331 {
332 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800333 EXPECT_FALSE(DBusAdaptor::SetProperty(service_->mutable_store(),
334 flimflam::kFavoriteProperty,
335 PropertyStoreTest::kBoolV,
336 &error));
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700337 ASSERT_TRUE(error.is_set()); // name() may be invalid otherwise
Chris Masone9d779932011-08-25 16:33:41 -0700338 EXPECT_EQ(invalid_args(), error.name());
Chris Masonea8a2c252011-06-27 22:16:30 -0700339 }
Thieu Le284fe792012-01-31 17:53:19 -0800340 {
341 ::DBus::Error error;
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700342 ::DBus::Variant auto_connect;
343 auto_connect.writer().append_bool(true);
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800344 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
345 flimflam::kAutoConnectProperty,
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700346 auto_connect,
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800347 &error));
Thieu Le284fe792012-01-31 17:53:19 -0800348 }
Paul Stewart0c438332012-04-11 07:55:27 -0700349 // Ensure that we can perform a trivial set of the Name property (to its
350 // current value) but an attempt to set the property to a different value
351 // fails.
352 {
353 ::DBus::Error error;
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700354 EXPECT_FALSE(DBusAdaptor::SetProperty(service_->mutable_store(),
355 flimflam::kNameProperty,
356 DBusAdaptor::StringToVariant(
357 GetFriendlyName()),
358 &error));
359 EXPECT_FALSE(error.is_set());
Paul Stewart0c438332012-04-11 07:55:27 -0700360 }
361 {
362 ::DBus::Error error;
363 EXPECT_FALSE(DBusAdaptor::SetProperty(service_->mutable_store(),
364 flimflam::kNameProperty,
365 PropertyStoreTest::kStringV,
366 &error));
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700367 ASSERT_TRUE(error.is_set()); // name() may be invalid otherwise
Paul Stewart0c438332012-04-11 07:55:27 -0700368 EXPECT_EQ(invalid_args(), error.name());
369 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700370}
371
Paul Stewarte7de2942013-04-25 17:07:31 -0700372TEST_F(ServiceTest, GetLoadableStorageIdentifier) {
373 NiceMock<MockStore> storage;
374 EXPECT_CALL(storage, ContainsGroup(storage_id_))
375 .WillOnce(Return(false))
376 .WillOnce(Return(true));
377 EXPECT_EQ("", service_->GetLoadableStorageIdentifier(storage));
378 EXPECT_EQ(storage_id_, service_->GetLoadableStorageIdentifier(storage));
379}
380
381TEST_F(ServiceTest, IsLoadableFrom) {
382 NiceMock<MockStore> storage;
383 EXPECT_CALL(storage, ContainsGroup(storage_id_))
384 .WillOnce(Return(false))
385 .WillOnce(Return(true));
386 EXPECT_FALSE(service_->IsLoadableFrom(storage));
387 EXPECT_TRUE(service_->IsLoadableFrom(storage));
388}
389
Darin Petkovba40dd32011-07-11 20:06:39 -0700390TEST_F(ServiceTest, Load) {
391 NiceMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700392 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
393 EXPECT_CALL(storage, GetString(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, GetBool(storage_id_, _, _)).Times(AnyNumber());
397 EXPECT_CALL(storage,
398 GetBool(storage_id_, Service::kStorageSaveCredentials, _));
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700399 EXPECT_CALL(*eap_, Load(&storage, storage_id_));
Chris Masone9d779932011-08-25 16:33:41 -0700400 EXPECT_TRUE(service_->Load(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700401}
402
403TEST_F(ServiceTest, LoadFail) {
404 StrictMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700405 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(false));
Chris Masone9d779932011-08-25 16:33:41 -0700406 EXPECT_FALSE(service_->Load(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700407}
408
409TEST_F(ServiceTest, SaveString) {
410 MockStore storage;
411 static const char kKey[] = "test-key";
412 static const char kData[] = "test-data";
Chris Masone34af2182011-08-22 11:59:36 -0700413 EXPECT_CALL(storage, SetString(storage_id_, kKey, kData))
Darin Petkovba40dd32011-07-11 20:06:39 -0700414 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700415 service_->SaveString(&storage, storage_id_, kKey, kData, false, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700416}
417
418TEST_F(ServiceTest, SaveStringCrypted) {
419 MockStore storage;
420 static const char kKey[] = "test-key";
421 static const char kData[] = "test-data";
Chris Masone34af2182011-08-22 11:59:36 -0700422 EXPECT_CALL(storage, SetCryptedString(storage_id_, kKey, kData))
Darin Petkovba40dd32011-07-11 20:06:39 -0700423 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700424 service_->SaveString(&storage, storage_id_, kKey, kData, true, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700425}
426
427TEST_F(ServiceTest, SaveStringDontSave) {
428 MockStore storage;
429 static const char kKey[] = "test-key";
Chris Masone34af2182011-08-22 11:59:36 -0700430 EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
Darin Petkovba40dd32011-07-11 20:06:39 -0700431 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700432 service_->SaveString(&storage, storage_id_, kKey, "data", false, false);
Darin Petkovba40dd32011-07-11 20:06:39 -0700433}
434
435TEST_F(ServiceTest, SaveStringEmpty) {
436 MockStore storage;
437 static const char kKey[] = "test-key";
Chris Masone34af2182011-08-22 11:59:36 -0700438 EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
Darin Petkovba40dd32011-07-11 20:06:39 -0700439 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700440 service_->SaveString(&storage, storage_id_, kKey, "", true, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700441}
442
443TEST_F(ServiceTest, Save) {
444 NiceMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700445 EXPECT_CALL(storage, SetString(storage_id_, _, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700446 .Times(AtLeast(1))
447 .WillRepeatedly(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700448 EXPECT_CALL(storage, DeleteKey(storage_id_, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700449 .Times(AtLeast(1))
450 .WillRepeatedly(Return(true));
Darin Petkov0debec02013-01-22 10:40:05 +0100451 EXPECT_CALL(storage, SetBool(storage_id_, _, _)).Times(AnyNumber());
452 EXPECT_CALL(storage,
453 SetBool(storage_id_,
454 Service::kStorageSaveCredentials,
455 service_->save_credentials()));
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700456 EXPECT_CALL(*eap_, Save(&storage, storage_id_, true));
Chris Masone9d779932011-08-25 16:33:41 -0700457 EXPECT_TRUE(service_->Save(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700458}
459
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800460TEST_F(ServiceTest, Unload) {
461 NiceMock<MockStore> storage;
462 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
463 static const string string_value("value");
464 EXPECT_CALL(storage, GetString(storage_id_, _, _))
465 .Times(AtLeast(1))
466 .WillRepeatedly(DoAll(SetArgumentPointee<2>(string_value), Return(true)));
Paul Stewart88769de2012-09-21 13:14:36 -0700467 EXPECT_CALL(storage, GetBool(storage_id_, _, _))
468 .Times(AtLeast(1))
469 .WillRepeatedly(DoAll(SetArgumentPointee<2>(true), Return(true)));
470 EXPECT_FALSE(service_->explicitly_disconnected_);
471 service_->explicitly_disconnected_ = true;
472 EXPECT_FALSE(service_->has_ever_connected_);
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700473 EXPECT_CALL(*eap_, Load(&storage, storage_id_));
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800474 ASSERT_TRUE(service_->Load(&storage));
Paul Stewarte7cce8f2012-09-11 10:56:38 -0700475 // TODO(pstew): Only two string properties in the service are tested as
mukesh agrawalcf24a242012-05-21 16:46:11 -0700476 // a sentinel that properties are being set and reset at the right times.
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800477 // However, since property load/store is essentially a manual process,
478 // it is error prone and should either be exhaustively unit-tested or
479 // a generic framework for registering loaded/stored properties should
480 // be created. crosbug.com/24859
481 EXPECT_EQ(string_value, service_->ui_data_);
Paul Stewarte7cce8f2012-09-11 10:56:38 -0700482 EXPECT_EQ(string_value, service_->guid_);
Paul Stewart88769de2012-09-21 13:14:36 -0700483 EXPECT_FALSE(service_->explicitly_disconnected_);
484 EXPECT_TRUE(service_->has_ever_connected_);
485 service_->explicitly_disconnected_ = true;
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700486 EXPECT_CALL(*eap_, Reset());
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800487 service_->Unload();
488 EXPECT_EQ(string(""), service_->ui_data_);
Paul Stewarte7cce8f2012-09-11 10:56:38 -0700489 EXPECT_EQ(string(""), service_->guid_);
Philipp Neubeckf883a7b2012-09-14 19:52:44 +0200490 EXPECT_FALSE(service_->explicitly_disconnected_);
Paul Stewart88769de2012-09-21 13:14:36 -0700491 EXPECT_FALSE(service_->has_ever_connected_);
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800492}
493
Paul Stewart03dba0b2011-08-22 16:32:45 -0700494TEST_F(ServiceTest, State) {
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400495 EXPECT_EQ(Service::kStateIdle, service_->state());
Darin Petkovc8d91e52013-01-21 11:43:47 +0100496 EXPECT_EQ(Service::kStateIdle, GetPreviousState());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700497 EXPECT_EQ(Service::kFailureUnknown, service_->failure());
Paul Stewartf2d60912012-07-15 08:37:30 -0700498 const string unknown_error(
499 Service::ConnectFailureToString(Service::kFailureUnknown));
500 EXPECT_EQ(unknown_error, service_->error());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700501
mukesh agrawal00917ce2011-11-22 23:56:55 +0000502 ServiceRefPtr service_ref(service_);
mukesh agrawalf2f68a52011-09-01 12:15:48 -0700503
Darin Petkovaba89322013-03-11 14:48:22 +0100504 EXPECT_CALL(*GetAdaptor(),
Wade Guthriecb094352013-05-08 15:24:59 -0700505 EmitStringChanged(flimflam::kStateProperty, _)).Times(6);
Darin Petkovaba89322013-03-11 14:48:22 +0100506 EXPECT_CALL(*GetAdaptor(),
Paul Stewartf2d60912012-07-15 08:37:30 -0700507 EmitStringChanged(flimflam::kErrorProperty, _)).Times(4);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700508 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
509 service_->SetState(Service::kStateConnected);
Darin Petkovc8d91e52013-01-21 11:43:47 +0100510 EXPECT_EQ(Service::kStateIdle, GetPreviousState());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700511 // A second state change shouldn't cause another update
512 service_->SetState(Service::kStateConnected);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700513 EXPECT_EQ(Service::kStateConnected, service_->state());
Darin Petkovc8d91e52013-01-21 11:43:47 +0100514 EXPECT_EQ(Service::kStateIdle, GetPreviousState());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700515 EXPECT_EQ(Service::kFailureUnknown, service_->failure());
mukesh agrawalcf24a242012-05-21 16:46:11 -0700516 EXPECT_TRUE(service_->has_ever_connected_);
mukesh agrawal568b5c62012-02-28 14:44:47 -0800517
Paul Stewart03dba0b2011-08-22 16:32:45 -0700518 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
Paul Stewart03dba0b2011-08-22 16:32:45 -0700519 service_->SetFailure(Service::kFailureOutOfRange);
mukesh agrawal568b5c62012-02-28 14:44:47 -0800520 EXPECT_TRUE(service_->IsFailed());
521 EXPECT_GT(service_->failed_time_, 0);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700522 EXPECT_EQ(Service::kStateFailure, service_->state());
523 EXPECT_EQ(Service::kFailureOutOfRange, service_->failure());
Paul Stewartf2d60912012-07-15 08:37:30 -0700524 const string out_of_range_error(
525 Service::ConnectFailureToString(Service::kFailureOutOfRange));
526 EXPECT_EQ(out_of_range_error, service_->error());
mukesh agrawal568b5c62012-02-28 14:44:47 -0800527
528 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
529 service_->SetState(Service::kStateConnected);
530 EXPECT_FALSE(service_->IsFailed());
531 EXPECT_EQ(service_->failed_time_, 0);
Paul Stewartf2d60912012-07-15 08:37:30 -0700532 EXPECT_EQ(unknown_error, service_->error());
mukesh agrawal568b5c62012-02-28 14:44:47 -0800533
534 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
535 service_->SetFailureSilent(Service::kFailurePinMissing);
536 EXPECT_TRUE(service_->IsFailed());
537 EXPECT_GT(service_->failed_time_, 0);
538 EXPECT_EQ(Service::kStateIdle, service_->state());
539 EXPECT_EQ(Service::kFailurePinMissing, service_->failure());
Paul Stewartf2d60912012-07-15 08:37:30 -0700540 const string pin_missing_error(
541 Service::ConnectFailureToString(Service::kFailurePinMissing));
542 EXPECT_EQ(pin_missing_error, service_->error());
mukesh agrawalcf24a242012-05-21 16:46:11 -0700543
544 // If the Service has a Profile, the profile should be saved when
545 // the service enters kStateConnected. (The case where the service
546 // doesn't have a profile is tested above.)
547 MockProfileRefPtr mock_profile(
Thieu Le5133b712013-02-19 14:47:21 -0800548 new MockProfile(control_interface(), metrics(), &mock_manager_));
mukesh agrawalcf24a242012-05-21 16:46:11 -0700549 NiceMock<MockStore> storage;
550 service_->set_profile(mock_profile);
551 service_->has_ever_connected_ = false;
552 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
553 EXPECT_CALL(*mock_profile, GetConstStorage())
554 .WillOnce(Return(&storage));
555 EXPECT_CALL(*mock_profile, UpdateService(service_ref));
556 service_->SetState(Service::kStateConnected);
557 EXPECT_TRUE(service_->has_ever_connected_);
558 service_->set_profile(NULL); // Break reference cycle.
559
560 // Similar to the above, but emulate an emphemeral profile, which
561 // has no storage. We can't update the service in the profile, but
562 // we should not crash.
563 service_->state_ = Service::kStateIdle; // Skips state change logic.
564 service_->set_profile(mock_profile);
565 service_->has_ever_connected_ = false;
566 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
567 EXPECT_CALL(*mock_profile, GetConstStorage()).
568 WillOnce(Return(static_cast<StoreInterface *>(NULL)));
569 service_->SetState(Service::kStateConnected);
570 EXPECT_TRUE(service_->has_ever_connected_);
571 service_->set_profile(NULL); // Break reference cycle.
Paul Stewart03dba0b2011-08-22 16:32:45 -0700572}
573
Thieu Leaf471412013-06-27 14:12:37 -0700574TEST_F(ServiceTest, StateResetAfterFailure) {
575 service_->SetFailure(Service::kFailureOutOfRange);
576 EXPECT_EQ(Service::kStateFailure, service_->state());
577 Error error;
578 service_->Connect(&error, "in test");
579 EXPECT_EQ(Service::kStateIdle, service_->state());
580 EXPECT_EQ(Service::kFailureUnknown, service_->failure());
581
582 service_->SetState(Service::kStateConnected);
583 service_->Connect(&error, "in test");
584 EXPECT_EQ(Service::kStateConnected, service_->state());
585}
586
Darin Petkovb100ae72011-08-24 16:19:45 -0700587TEST_F(ServiceTest, ActivateCellularModem) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500588 ResultCallback callback =
589 Bind(&ServiceTest::TestCallback, Unretained(this));
590 EXPECT_CALL(*this, TestCallback(_)).Times(0);
Darin Petkovb100ae72011-08-24 16:19:45 -0700591 Error error;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500592 service_->ActivateCellularModem("Carrier", &error, callback);
593 EXPECT_TRUE(error.IsFailure());
Darin Petkovb100ae72011-08-24 16:19:45 -0700594}
595
Ben Chan5d924542013-02-14 17:49:08 -0800596TEST_F(ServiceTest, CompleteCellularActivation) {
597 Error error;
598 service_->CompleteCellularActivation(&error);
599 EXPECT_EQ(Error::kNotSupported, error.type());
600}
601
mukesh agrawal00917ce2011-11-22 23:56:55 +0000602TEST_F(ServiceTest, MakeFavorite) {
603 EXPECT_FALSE(service_->favorite());
604 EXPECT_FALSE(service_->auto_connect());
605
606 service_->MakeFavorite();
607 EXPECT_TRUE(service_->favorite());
608 EXPECT_TRUE(service_->auto_connect());
609}
610
611TEST_F(ServiceTest, ReMakeFavorite) {
612 service_->MakeFavorite();
613 EXPECT_TRUE(service_->favorite());
614 EXPECT_TRUE(service_->auto_connect());
615
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700616 service_->SetAutoConnect(false);
mukesh agrawal00917ce2011-11-22 23:56:55 +0000617 service_->MakeFavorite();
618 EXPECT_TRUE(service_->favorite());
619 EXPECT_FALSE(service_->auto_connect());
620}
621
mukesh agrawal76d13882012-01-12 15:23:11 -0800622TEST_F(ServiceTest, IsAutoConnectable) {
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100623 const char *reason = NULL;
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700624 service_->SetConnectable(true);
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100625
626 // Services with non-primary connectivity technologies should not auto-connect
627 // when the system is offline.
628 EXPECT_EQ(Technology::kUnknown, service_->technology());
629 EXPECT_CALL(mock_manager_, IsOnline()).WillOnce(Return(false));
630 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
631 EXPECT_STREQ(Service::kAutoConnOffline, reason);
632
633 service_->technology_ = Technology::kEthernet;
mukesh agrawalbf14e942012-03-02 14:36:34 -0800634 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawal76d13882012-01-12 15:23:11 -0800635
mukesh agrawaladb68482012-01-17 16:31:51 -0800636 // We should not auto-connect to a Service that a user has
637 // deliberately disconnected.
638 Error error;
Christopher Wileyabd3b502012-09-26 13:08:52 -0700639 service_->UserInitiatedDisconnect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800640 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
641 EXPECT_STREQ(Service::kAutoConnExplicitDisconnect, reason);
mukesh agrawaladb68482012-01-17 16:31:51 -0800642
643 // But if the Service is reloaded, it is eligible for auto-connect
644 // again.
645 NiceMock<MockStore> storage;
646 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700647 EXPECT_CALL(*eap_, Load(&storage, storage_id_));
mukesh agrawaladb68482012-01-17 16:31:51 -0800648 EXPECT_TRUE(service_->Load(&storage));
mukesh agrawalbf14e942012-03-02 14:36:34 -0800649 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800650
651 // A deliberate Connect should also re-enable auto-connect.
Christopher Wileyabd3b502012-09-26 13:08:52 -0700652 service_->UserInitiatedDisconnect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800653 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700654 service_->Connect(&error, "in test");
mukesh agrawalbf14e942012-03-02 14:36:34 -0800655 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800656
Christopher Wileyabd3b502012-09-26 13:08:52 -0700657 // A non-user initiated Disconnect doesn't change anything.
658 service_->Disconnect(&error);
659 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
660
Christopher Wileya4c61ae2012-10-01 11:04:30 -0700661 // A resume also re-enables auto-connect.
662 service_->UserInitiatedDisconnect(&error);
663 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
664 service_->OnAfterResume();
665 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800666
mukesh agrawal76d13882012-01-12 15:23:11 -0800667 service_->SetState(Service::kStateConnected);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800668 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
669 EXPECT_STREQ(Service::kAutoConnConnected, reason);
mukesh agrawal76d13882012-01-12 15:23:11 -0800670
671 service_->SetState(Service::kStateAssociating);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800672 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
673 EXPECT_STREQ(Service::kAutoConnConnecting, reason);
mukesh agrawal76d13882012-01-12 15:23:11 -0800674}
675
mukesh agrawal03c15ce2012-11-29 17:36:21 -0800676TEST_F(ServiceTest, AutoConnectLogging) {
677 ScopedMockLog log;
678 EXPECT_CALL(log, Log(_, _, _));
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700679 service_->SetConnectable(true);
mukesh agrawal03c15ce2012-11-29 17:36:21 -0800680
681 ScopeLogger::GetInstance()->EnableScopesByName("+service");
682 ScopeLogger::GetInstance()->set_verbose_level(1);
683 service_->SetState(Service::kStateConnected);
684 EXPECT_CALL(log, Log(-1, _, HasSubstr(Service::kAutoConnConnected)));
685 service_->AutoConnect();
686
687 ScopeLogger::GetInstance()->EnableScopesByName("-service");
688 ScopeLogger::GetInstance()->set_verbose_level(0);
689 EXPECT_CALL(log, Log(logging::LOG_INFO, _,
690 HasSubstr(Service::kAutoConnNotConnectable)));
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700691 service_->SetConnectable(false);
mukesh agrawal03c15ce2012-11-29 17:36:21 -0800692 service_->AutoConnect();
693}
694
695
Christopher Wiley0801d192012-09-24 11:57:15 -0700696TEST_F(AllMockServiceTest, AutoConnectWithFailures) {
697 const char *reason;
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700698 service_->SetConnectable(true);
Darin Petkov4cbff5b2013-01-29 16:29:05 +0100699 service_->technology_ = Technology::kEthernet;
Christopher Wiley0801d192012-09-24 11:57:15 -0700700 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
701
702 // The very first AutoConnect() doesn't trigger any throttling.
703 EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(0);
704 service_->AutoConnect();
705 Mock::VerifyAndClearExpectations(&dispatcher_);
706 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
707
708 // The second call does trigger some throttling.
709 EXPECT_CALL(dispatcher_, PostDelayedTask(_,
710 Service::kMinAutoConnectCooldownTimeMilliseconds));
711 service_->AutoConnect();
712 Mock::VerifyAndClearExpectations(&dispatcher_);
713 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
714 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
715
716 // Calling AutoConnect() again before the cooldown terminates does not change
717 // the timeout.
718 EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(0);
719 service_->AutoConnect();
720 Mock::VerifyAndClearExpectations(&dispatcher_);
721 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
722 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
723
724 // Once the timeout expires, we can AutoConnect() again.
725 service_->ReEnableAutoConnectTask();
726 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
727
728 // Timeouts increase exponentially.
729 uint64 next_cooldown_time = service_->auto_connect_cooldown_milliseconds_;
730 EXPECT_EQ(next_cooldown_time,
731 Service::kAutoConnectCooldownBackoffFactor *
732 Service::kMinAutoConnectCooldownTimeMilliseconds);
733 while (next_cooldown_time <=
734 Service::kMaxAutoConnectCooldownTimeMilliseconds) {
735 EXPECT_CALL(dispatcher_, PostDelayedTask(_, next_cooldown_time));
736 service_->AutoConnect();
737 Mock::VerifyAndClearExpectations(&dispatcher_);
738 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
739 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
740 service_->ReEnableAutoConnectTask();
741 next_cooldown_time *= Service::kAutoConnectCooldownBackoffFactor;
742 }
743
744 // Once we hit our cap, future timeouts are the same.
745 for (int32 i = 0; i < 2; i++) {
746 EXPECT_CALL(dispatcher_, PostDelayedTask(_,
747 Service::kMaxAutoConnectCooldownTimeMilliseconds));
748 service_->AutoConnect();
749 Mock::VerifyAndClearExpectations(&dispatcher_);
750 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
751 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
752 service_->ReEnableAutoConnectTask();
753 }
754
755 // Connecting successfully resets our cooldown.
756 service_->SetState(Service::kStateConnected);
757 service_->SetState(Service::kStateIdle);
758 reason = "";
759 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
760 EXPECT_STREQ("", reason);
761 EXPECT_EQ(service_->auto_connect_cooldown_milliseconds_, 0);
762
763 // But future AutoConnects behave as before
764 EXPECT_CALL(dispatcher_, PostDelayedTask(_,
765 Service::kMinAutoConnectCooldownTimeMilliseconds)).Times(1);
766 service_->AutoConnect();
767 service_->AutoConnect();
768 Mock::VerifyAndClearExpectations(&dispatcher_);
769 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
770 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
771
772 // Cooldowns are forgotten if we go through a suspend/resume cycle.
773 service_->OnAfterResume();
774 reason = "";
775 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
776 EXPECT_STREQ("", reason);
777}
778
Paul Stewartcb59fed2012-03-21 21:14:46 -0700779TEST_F(ServiceTest, ConfigureBadProperty) {
780 KeyValueStore args;
781 args.SetString("XXXInvalid", "Value");
782 Error error;
783 service_->Configure(args, &error);
784 EXPECT_FALSE(error.IsSuccess());
785}
786
787TEST_F(ServiceTest, ConfigureBoolProperty) {
788 service_->MakeFavorite();
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700789 service_->SetAutoConnect(false);
Paul Stewartcb59fed2012-03-21 21:14:46 -0700790 ASSERT_FALSE(service_->auto_connect());
791 KeyValueStore args;
792 args.SetBool(flimflam::kAutoConnectProperty, true);
793 Error error;
794 service_->Configure(args, &error);
795 EXPECT_TRUE(error.IsSuccess());
796 EXPECT_TRUE(service_->auto_connect());
797}
798
799TEST_F(ServiceTest, ConfigureStringProperty) {
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700800 const string kGuid0 = "guid_zero";
801 const string kGuid1 = "guid_one";
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700802 service_->SetGuid(kGuid0, NULL);
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700803 ASSERT_EQ(kGuid0, service_->guid());
Paul Stewartcb59fed2012-03-21 21:14:46 -0700804 KeyValueStore args;
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700805 args.SetString(flimflam::kGuidProperty, kGuid1);
Paul Stewartcb59fed2012-03-21 21:14:46 -0700806 Error error;
807 service_->Configure(args, &error);
808 EXPECT_TRUE(error.IsSuccess());
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700809 EXPECT_EQ(kGuid1, service_->guid());
810}
811
Paul Stewart99dc9f32013-06-27 07:39:25 -0700812TEST_F(ServiceTest, ConfigureStringsProperty) {
813 const vector<string> kStrings0{ "string0", "string1" };
814 const vector<string> kStrings1{ "string2", "string3" };
815 service_->set_strings(kStrings0);
816 ASSERT_EQ(kStrings0, service_->strings());
817 KeyValueStore args;
818 args.SetStrings(ServiceUnderTest::kStringsProperty, kStrings1);
819 Error error;
820 service_->Configure(args, &error);
821 EXPECT_TRUE(error.IsSuccess());
822 EXPECT_EQ(kStrings1, service_->strings());
823}
824
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700825TEST_F(ServiceTest, ConfigureEapStringProperty) {
826 MockEapCredentials *eap = new MockEapCredentials();
827 service2_->SetEapCredentials(eap); // Passes ownership.
828
829 const string kEAPManagement0 = "management_zero";
830 const string kEAPManagement1 = "management_one";
831 service2_->SetEAPKeyManagement(kEAPManagement0);
832
833 EXPECT_CALL(*eap, key_management())
834 .WillOnce(ReturnRef(kEAPManagement0));
835 ASSERT_EQ(kEAPManagement0, service2_->GetEAPKeyManagement());
836 KeyValueStore args;
837 EXPECT_CALL(*eap, SetKeyManagement(kEAPManagement1, _));
838 args.SetString(flimflam::kEapKeyMgmtProperty, kEAPManagement1);
839 Error error;
840 service2_->Configure(args, &error);
841 EXPECT_TRUE(error.IsSuccess());
Paul Stewartcb59fed2012-03-21 21:14:46 -0700842}
843
Paul Stewart7a20aa42013-01-17 12:21:41 -0800844TEST_F(ServiceTest, ConfigureIntProperty) {
845 const int kPriority0 = 100;
846 const int kPriority1 = 200;
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700847 service_->SetPriority(kPriority0, NULL);
Paul Stewart7a20aa42013-01-17 12:21:41 -0800848 ASSERT_EQ(kPriority0, service_->priority());
849 KeyValueStore args;
850 args.SetInt(flimflam::kPriorityProperty, kPriority1);
851 Error error;
852 service_->Configure(args, &error);
853 EXPECT_TRUE(error.IsSuccess());
854 EXPECT_EQ(kPriority1, service_->priority());
855}
856
Paul Stewartcb59fed2012-03-21 21:14:46 -0700857TEST_F(ServiceTest, ConfigureIgnoredProperty) {
858 service_->MakeFavorite();
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700859 service_->SetAutoConnect(false);
Paul Stewartcb59fed2012-03-21 21:14:46 -0700860 ASSERT_FALSE(service_->auto_connect());
861 KeyValueStore args;
862 args.SetBool(flimflam::kAutoConnectProperty, true);
863 Error error;
864 service_->IgnoreParameterForConfigure(flimflam::kAutoConnectProperty);
865 service_->Configure(args, &error);
866 EXPECT_TRUE(error.IsSuccess());
867 EXPECT_FALSE(service_->auto_connect());
868}
869
Paul Stewart7a20aa42013-01-17 12:21:41 -0800870TEST_F(ServiceTest, DoPropertiesMatch) {
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700871 service_->SetAutoConnect(false);
Paul Stewart7a20aa42013-01-17 12:21:41 -0800872 const string kGUID0 = "guid_zero";
873 const string kGUID1 = "guid_one";
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700874 service_->SetGuid(kGUID0, NULL);
Paul Stewart7a20aa42013-01-17 12:21:41 -0800875 const uint32 kPriority0 = 100;
876 const uint32 kPriority1 = 200;
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700877 service_->SetPriority(kPriority0, NULL);
Paul Stewart99dc9f32013-06-27 07:39:25 -0700878 const vector<string> kStrings0{ "string0", "string1" };
879 const vector<string> kStrings1{ "string2", "string3" };
880 service_->set_strings(kStrings0);
Paul Stewart7a20aa42013-01-17 12:21:41 -0800881
882 {
883 KeyValueStore args;
884 args.SetString(flimflam::kGuidProperty, kGUID0);
885 args.SetBool(flimflam::kAutoConnectProperty, false);
886 args.SetInt(flimflam::kPriorityProperty, kPriority0);
Paul Stewart99dc9f32013-06-27 07:39:25 -0700887 args.SetStrings(ServiceUnderTest::kStringsProperty, kStrings0);
Paul Stewart7a20aa42013-01-17 12:21:41 -0800888 EXPECT_TRUE(service_->DoPropertiesMatch(args));
889 }
890 {
891 KeyValueStore args;
892 args.SetString(flimflam::kGuidProperty, kGUID1);
893 args.SetBool(flimflam::kAutoConnectProperty, false);
894 args.SetInt(flimflam::kPriorityProperty, kPriority0);
Paul Stewart99dc9f32013-06-27 07:39:25 -0700895 args.SetStrings(ServiceUnderTest::kStringsProperty, kStrings0);
Paul Stewart7a20aa42013-01-17 12:21:41 -0800896 EXPECT_FALSE(service_->DoPropertiesMatch(args));
897 }
898 {
899 KeyValueStore args;
900 args.SetString(flimflam::kGuidProperty, kGUID0);
901 args.SetBool(flimflam::kAutoConnectProperty, true);
902 args.SetInt(flimflam::kPriorityProperty, kPriority0);
Paul Stewart99dc9f32013-06-27 07:39:25 -0700903 args.SetStrings(ServiceUnderTest::kStringsProperty, kStrings0);
Paul Stewart7a20aa42013-01-17 12:21:41 -0800904 EXPECT_FALSE(service_->DoPropertiesMatch(args));
905 }
906 {
907 KeyValueStore args;
908 args.SetString(flimflam::kGuidProperty, kGUID0);
909 args.SetBool(flimflam::kAutoConnectProperty, false);
910 args.SetInt(flimflam::kPriorityProperty, kPriority1);
Paul Stewart99dc9f32013-06-27 07:39:25 -0700911 args.SetStrings(ServiceUnderTest::kStringsProperty, kStrings0);
912 EXPECT_FALSE(service_->DoPropertiesMatch(args));
913 }
914 {
915 KeyValueStore args;
916 args.SetString(flimflam::kGuidProperty, kGUID0);
917 args.SetBool(flimflam::kAutoConnectProperty, false);
918 args.SetInt(flimflam::kPriorityProperty, kPriority0);
919 args.SetStrings(ServiceUnderTest::kStringsProperty, kStrings1);
Paul Stewart7a20aa42013-01-17 12:21:41 -0800920 EXPECT_FALSE(service_->DoPropertiesMatch(args));
921 }
922}
923
Paul Stewart10ccbb32012-04-26 15:59:30 -0700924TEST_F(ServiceTest, IsRemembered) {
925 ServiceConstRefPtr service_ref(service_);
926 service_->set_profile(NULL);
927 EXPECT_CALL(mock_manager_, IsServiceEphemeral(_)).Times(0);
928 EXPECT_FALSE(service_->IsRemembered());
929
930 scoped_refptr<MockProfile> profile(
Thieu Le5133b712013-02-19 14:47:21 -0800931 new StrictMock<MockProfile>(control_interface(), metrics(), manager()));
Paul Stewart10ccbb32012-04-26 15:59:30 -0700932 service_->set_profile(profile);
933 EXPECT_CALL(mock_manager_, IsServiceEphemeral(service_ref))
934 .WillOnce(Return(true))
935 .WillOnce(Return(false));
936 EXPECT_FALSE(service_->IsRemembered());
937 EXPECT_TRUE(service_->IsRemembered());
938}
939
Paul Stewartdf3c0a82012-11-09 15:54:33 -0800940TEST_F(ServiceTest, IsDependentOn) {
941 EXPECT_FALSE(service_->IsDependentOn(NULL));
942
943 scoped_ptr<MockDeviceInfo> mock_device_info(
944 new NiceMock<MockDeviceInfo>(control_interface(), dispatcher(), metrics(),
945 &mock_manager_));
946 scoped_refptr<MockConnection> mock_connection0(
947 new NiceMock<MockConnection>(mock_device_info.get()));
948 scoped_refptr<MockConnection> mock_connection1(
949 new NiceMock<MockConnection>(mock_device_info.get()));
950
951 service_->connection_ = mock_connection0;
Paul Stewartcd7f5852013-03-27 13:54:23 -0700952 EXPECT_CALL(*mock_connection0, GetLowerConnection())
Paul Stewartdf3c0a82012-11-09 15:54:33 -0800953 .WillRepeatedly(Return(mock_connection1));
Paul Stewartcd7f5852013-03-27 13:54:23 -0700954 EXPECT_CALL(*mock_connection1, GetLowerConnection())
955 .WillRepeatedly(Return(ConnectionRefPtr()));
Paul Stewartdf3c0a82012-11-09 15:54:33 -0800956 EXPECT_FALSE(service_->IsDependentOn(NULL));
957
958 scoped_refptr<ServiceUnderTest> service1 =
959 new ServiceUnderTest(control_interface(),
960 dispatcher(),
961 metrics(),
962 &mock_manager_);
963 EXPECT_FALSE(service_->IsDependentOn(service1));
964
965 service1->connection_ = mock_connection0;
966 EXPECT_FALSE(service_->IsDependentOn(service1));
967
968 service1->connection_ = mock_connection1;
969 EXPECT_TRUE(service_->IsDependentOn(service1));
970
Paul Stewartcd7f5852013-03-27 13:54:23 -0700971 service_->connection_ = mock_connection1;
Paul Stewartdf3c0a82012-11-09 15:54:33 -0800972 service1->connection_ = NULL;
Paul Stewartcd7f5852013-03-27 13:54:23 -0700973 EXPECT_FALSE(service_->IsDependentOn(service1));
974
975 service_->connection_ = NULL;
Paul Stewartdf3c0a82012-11-09 15:54:33 -0800976}
977
Paul Stewartff14b022012-04-24 20:06:23 -0700978TEST_F(ServiceTest, OnPropertyChanged) {
979 scoped_refptr<MockProfile> profile(
Thieu Le5133b712013-02-19 14:47:21 -0800980 new StrictMock<MockProfile>(control_interface(), metrics(), manager()));
Paul Stewartff14b022012-04-24 20:06:23 -0700981 service_->set_profile(NULL);
982 // Expect no crash.
983 service_->OnPropertyChanged("");
984
985 // Expect no call to Update if the profile has no storage.
986 service_->set_profile(profile);
987 EXPECT_CALL(*profile, UpdateService(_)).Times(0);
988 EXPECT_CALL(*profile, GetConstStorage())
989 .WillOnce(Return(reinterpret_cast<StoreInterface *>(NULL)));
990 service_->OnPropertyChanged("");
991
992 // Expect call to Update if the profile has storage.
993 EXPECT_CALL(*profile, UpdateService(_)).Times(1);
994 NiceMock<MockStore> storage;
995 EXPECT_CALL(*profile, GetConstStorage()).WillOnce(Return(&storage));
996 service_->OnPropertyChanged("");
997}
998
Paul Stewartd215af62012-04-24 23:25:50 -0700999
1000TEST_F(ServiceTest, RecheckPortal) {
1001 ServiceRefPtr service_ref(service_);
1002 service_->state_ = Service::kStateIdle;
1003 EXPECT_CALL(mock_manager_, RecheckPortalOnService(_)).Times(0);
1004 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
1005
1006 service_->state_ = Service::kStatePortal;
1007 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
1008 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
1009
1010 service_->state_ = Service::kStateConnected;
1011 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
1012 service_->OnPropertyChanged(flimflam::kProxyConfigProperty);
1013
1014 service_->state_ = Service::kStateOnline;
1015 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
1016 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
1017
1018 service_->state_ = Service::kStatePortal;
1019 EXPECT_CALL(mock_manager_, RecheckPortalOnService(_)).Times(0);
1020 service_->OnPropertyChanged(flimflam::kEAPKeyIDProperty);
1021}
1022
1023TEST_F(ServiceTest, SetCheckPortal) {
1024 ServiceRefPtr service_ref(service_);
1025 {
1026 Error error;
1027 service_->SetCheckPortal("false", &error);
1028 EXPECT_TRUE(error.IsSuccess());
1029 EXPECT_EQ(Service::kCheckPortalFalse, service_->check_portal_);
1030 }
1031 {
1032 Error error;
1033 service_->SetCheckPortal("true", &error);
1034 EXPECT_TRUE(error.IsSuccess());
1035 EXPECT_EQ(Service::kCheckPortalTrue, service_->check_portal_);
1036 }
1037 {
1038 Error error;
1039 service_->SetCheckPortal("auto", &error);
1040 EXPECT_TRUE(error.IsSuccess());
1041 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
1042 }
1043 {
1044 Error error;
1045 service_->SetCheckPortal("xxx", &error);
1046 EXPECT_FALSE(error.IsSuccess());
1047 EXPECT_EQ(Error::kInvalidArguments, error.type());
1048 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
1049 }
1050}
1051
Arman Uguray2717a102013-01-29 23:36:06 -08001052TEST_F(ServiceTest, SetFriendlyName) {
1053 EXPECT_EQ(service_->unique_name_, service_->friendly_name_);
Darin Petkovaba89322013-03-11 14:48:22 +01001054 ServiceMockAdaptor *adaptor = GetAdaptor();
Arman Uguray2717a102013-01-29 23:36:06 -08001055
1056 EXPECT_CALL(*adaptor, EmitStringChanged(_, _)).Times(0);
1057 service_->SetFriendlyName(service_->unique_name_);
1058 EXPECT_EQ(service_->unique_name_, service_->friendly_name_);
1059
1060 EXPECT_CALL(*adaptor, EmitStringChanged(flimflam::kNameProperty,
1061 "Test Name 1"));
1062 service_->SetFriendlyName("Test Name 1");
1063 EXPECT_EQ("Test Name 1", service_->friendly_name_);
1064
1065 EXPECT_CALL(*adaptor, EmitStringChanged(_, _)).Times(0);
1066 service_->SetFriendlyName("Test Name 1");
1067 EXPECT_EQ("Test Name 1", service_->friendly_name_);
1068
1069 EXPECT_CALL(*adaptor, EmitStringChanged(flimflam::kNameProperty,
1070 "Test Name 2"));
1071 service_->SetFriendlyName("Test Name 2");
1072 EXPECT_EQ("Test Name 2", service_->friendly_name_);
1073}
1074
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001075TEST_F(ServiceTest, SetConnectableFull) {
Darin Petkovb2ba39f2012-06-06 10:33:43 +02001076 EXPECT_FALSE(service_->connectable());
1077
Darin Petkovaba89322013-03-11 14:48:22 +01001078 ServiceMockAdaptor *adaptor = GetAdaptor();
Darin Petkovb2ba39f2012-06-06 10:33:43 +02001079
1080 EXPECT_CALL(*adaptor, EmitBoolChanged(_, _)).Times(0);
1081 EXPECT_CALL(mock_manager_, HasService(_)).Times(0);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001082 service_->SetConnectableFull(false);
Darin Petkovb2ba39f2012-06-06 10:33:43 +02001083 EXPECT_FALSE(service_->connectable());
1084
1085 EXPECT_CALL(*adaptor, EmitBoolChanged(flimflam::kConnectableProperty, true));
1086 EXPECT_CALL(mock_manager_, HasService(_)).WillOnce(Return(false));
1087 EXPECT_CALL(mock_manager_, UpdateService(_)).Times(0);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001088 service_->SetConnectableFull(true);
Darin Petkovb2ba39f2012-06-06 10:33:43 +02001089 EXPECT_TRUE(service_->connectable());
1090
1091 EXPECT_CALL(*adaptor, EmitBoolChanged(flimflam::kConnectableProperty, false));
1092 EXPECT_CALL(mock_manager_, HasService(_)).WillOnce(Return(true));
1093 EXPECT_CALL(mock_manager_, UpdateService(_));
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001094 service_->SetConnectableFull(false);
Darin Petkovb2ba39f2012-06-06 10:33:43 +02001095 EXPECT_FALSE(service_->connectable());
1096
1097 EXPECT_CALL(*adaptor, EmitBoolChanged(flimflam::kConnectableProperty, true));
1098 EXPECT_CALL(mock_manager_, HasService(_)).WillOnce(Return(true));
1099 EXPECT_CALL(mock_manager_, UpdateService(_));
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001100 service_->SetConnectableFull(true);
Darin Petkovb2ba39f2012-06-06 10:33:43 +02001101 EXPECT_TRUE(service_->connectable());
1102}
1103
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001104class WriteOnlyServicePropertyTest : public ServiceTest {};
1105TEST_P(WriteOnlyServicePropertyTest, PropertyWriteOnly) {
1106 // Use a real EapCredentials instance since the base Service class
1107 // contains no write-only properties.
1108 EapCredentials eap;
1109 eap.InitPropertyStore(service_->mutable_store());
1110
Paul Stewart9f32d192012-01-30 20:37:50 -08001111 string property(GetParam().reader().get_string());
Paul Stewarte6e8e492013-01-17 11:00:50 -08001112 Error error;
1113 EXPECT_FALSE(service_->store().GetStringProperty(property, NULL, &error));
1114 EXPECT_EQ(Error::kPermissionDenied, error.type());
Paul Stewart9f32d192012-01-30 20:37:50 -08001115}
1116
1117INSTANTIATE_TEST_CASE_P(
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001118 WriteOnlyServicePropertyTestInstance,
1119 WriteOnlyServicePropertyTest,
Paul Stewart9f32d192012-01-30 20:37:50 -08001120 Values(
1121 DBusAdaptor::StringToVariant(flimflam::kEapPrivateKeyPasswordProperty),
1122 DBusAdaptor::StringToVariant(flimflam::kEapPasswordProperty)));
1123
Paul Stewart10241e32012-04-23 18:15:06 -07001124
1125TEST_F(ServiceTest, GetIPConfigRpcIdentifier) {
1126 {
1127 Error error;
1128 EXPECT_EQ("/", service_->GetIPConfigRpcIdentifier(&error));
1129 EXPECT_EQ(Error::kNotFound, error.type());
1130 }
1131
1132 scoped_ptr<MockDeviceInfo> mock_device_info(
1133 new NiceMock<MockDeviceInfo>(control_interface(), dispatcher(), metrics(),
1134 &mock_manager_));
1135 scoped_refptr<MockConnection> mock_connection(
1136 new NiceMock<MockConnection>(mock_device_info.get()));
1137
1138 service_->connection_ = mock_connection;
1139
1140 {
1141 Error error;
1142 const string empty_string;
1143 EXPECT_CALL(*mock_connection, ipconfig_rpc_identifier())
1144 .WillOnce(ReturnRef(empty_string));
1145 EXPECT_EQ("/", service_->GetIPConfigRpcIdentifier(&error));
1146 EXPECT_EQ(Error::kNotFound, error.type());
1147 }
1148
1149 {
1150 Error error;
1151 const string nonempty_string("/ipconfig/path");
1152 EXPECT_CALL(*mock_connection, ipconfig_rpc_identifier())
1153 .WillOnce(ReturnRef(nonempty_string));
1154 EXPECT_EQ(nonempty_string, service_->GetIPConfigRpcIdentifier(&error));
1155 EXPECT_EQ(Error::kSuccess, error.type());
1156 }
1157
1158 // Assure orderly destruction of the Connection before DeviceInfo.
1159 service_->connection_ = NULL;
1160 mock_connection = NULL;
1161 mock_device_info.reset();
1162}
1163
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001164class ServiceWithMockOnEapCredentialsChanged : public ServiceUnderTest {
Paul Stewart81426132012-05-16 10:05:10 -07001165 public:
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001166 ServiceWithMockOnEapCredentialsChanged(ControlInterface *control_interface,
1167 EventDispatcher *dispatcher,
1168 Metrics *metrics,
1169 Manager *manager)
Paul Stewart81426132012-05-16 10:05:10 -07001170 : ServiceUnderTest(control_interface, dispatcher, metrics, manager),
1171 is_8021x_(false) {}
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001172 MOCK_METHOD0(OnEapCredentialsChanged, void());
Paul Stewart81426132012-05-16 10:05:10 -07001173 virtual bool Is8021x() const { return is_8021x_; }
1174 void set_is_8021x(bool is_8021x) { is_8021x_ = is_8021x; }
1175
1176 private:
1177 bool is_8021x_;
1178};
1179
1180TEST_F(ServiceTest, SetEAPCredentialsOverRPC) {
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001181 scoped_refptr<ServiceWithMockOnEapCredentialsChanged> service(
1182 new ServiceWithMockOnEapCredentialsChanged(control_interface(),
1183 dispatcher(),
1184 metrics(),
1185 &mock_manager_));
Paul Stewart81426132012-05-16 10:05:10 -07001186 string eap_credential_properties[] = {
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001187 flimflam::kEapAnonymousIdentityProperty,
Paul Stewart81426132012-05-16 10:05:10 -07001188 flimflam::kEAPCertIDProperty,
1189 flimflam::kEAPClientCertProperty,
Paul Stewart81426132012-05-16 10:05:10 -07001190 flimflam::kEapIdentityProperty,
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001191 flimflam::kEAPKeyIDProperty,
Paul Stewart81426132012-05-16 10:05:10 -07001192 flimflam::kEapPasswordProperty,
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001193 flimflam::kEAPPINProperty,
1194 flimflam::kEapPrivateKeyProperty,
1195 flimflam::kEapPrivateKeyPasswordProperty
Paul Stewart81426132012-05-16 10:05:10 -07001196 };
1197 string eap_non_credential_properties[] = {
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001198 flimflam::kEapCaCertIDProperty,
1199 flimflam::kEapCaCertNssProperty,
Paul Stewart81426132012-05-16 10:05:10 -07001200 flimflam::kEAPEAPProperty,
1201 flimflam::kEapPhase2AuthProperty,
Paul Stewart81426132012-05-16 10:05:10 -07001202 flimflam::kEapUseSystemCAsProperty
1203 };
1204 // While this is not an 802.1x-based service, none of these property
1205 // changes should cause a call to set_eap().
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001206 EXPECT_CALL(*service, OnEapCredentialsChanged()).Times(0);
Paul Stewart81426132012-05-16 10:05:10 -07001207 for (size_t i = 0; i < arraysize(eap_credential_properties); ++i)
1208 service->OnPropertyChanged(eap_credential_properties[i]);
1209 for (size_t i = 0; i < arraysize(eap_non_credential_properties); ++i)
1210 service->OnPropertyChanged(eap_non_credential_properties[i]);
Paul Stewartadf79d82012-07-18 16:09:56 -07001211 service->OnPropertyChanged(flimflam::kEapKeyMgmtProperty);
Paul Stewart81426132012-05-16 10:05:10 -07001212
1213 service->set_is_8021x(true);
1214
1215 // When this is an 802.1x-based service, set_eap should be called for
1216 // all credential-carrying properties.
1217 for (size_t i = 0; i < arraysize(eap_credential_properties); ++i) {
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001218 EXPECT_CALL(*service, OnEapCredentialsChanged()).Times(1);
Paul Stewart81426132012-05-16 10:05:10 -07001219 service->OnPropertyChanged(eap_credential_properties[i]);
1220 Mock::VerifyAndClearExpectations(service.get());
1221 }
Paul Stewartadf79d82012-07-18 16:09:56 -07001222
1223 // The key management property is a special case. While not strictly
1224 // a credential, it can change which credentials are used. Therefore it
1225 // should also trigger a call to set_eap();
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001226 EXPECT_CALL(*service, OnEapCredentialsChanged()).Times(1);
Paul Stewartadf79d82012-07-18 16:09:56 -07001227 service->OnPropertyChanged(flimflam::kEapKeyMgmtProperty);
1228 Mock::VerifyAndClearExpectations(service.get());
1229
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001230 EXPECT_CALL(*service, OnEapCredentialsChanged()).Times(0);
Paul Stewart81426132012-05-16 10:05:10 -07001231 for (size_t i = 0; i < arraysize(eap_non_credential_properties); ++i)
1232 service->OnPropertyChanged(eap_non_credential_properties[i]);
1233}
1234
Paul Stewartbc6e7392012-05-24 07:07:48 -07001235TEST_F(ServiceTest, Certification) {
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001236 EXPECT_FALSE(service_->remote_certification_.size());
Paul Stewartbc6e7392012-05-24 07:07:48 -07001237
1238 ScopedMockLog log;
1239 EXPECT_CALL(log, Log(logging::LOG_WARNING, _,
1240 HasSubstr("exceeds our maximum"))).Times(2);
1241 string kSubject("foo");
1242 EXPECT_FALSE(service_->AddEAPCertification(
1243 kSubject, Service::kEAPMaxCertificationElements));
1244 EXPECT_FALSE(service_->AddEAPCertification(
1245 kSubject, Service::kEAPMaxCertificationElements + 1));
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001246 EXPECT_FALSE(service_->remote_certification_.size());
Paul Stewartbc6e7392012-05-24 07:07:48 -07001247 Mock::VerifyAndClearExpectations(&log);
1248
1249 EXPECT_CALL(log,
1250 Log(logging::LOG_INFO, _, HasSubstr("Received certification")))
1251 .Times(1);
1252 EXPECT_TRUE(service_->AddEAPCertification(
1253 kSubject, Service::kEAPMaxCertificationElements - 1));
1254 Mock::VerifyAndClearExpectations(&log);
1255 EXPECT_EQ(Service::kEAPMaxCertificationElements,
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001256 service_->remote_certification_.size());
Paul Stewartbc6e7392012-05-24 07:07:48 -07001257 for (size_t i = 0; i < Service::kEAPMaxCertificationElements - 1; ++i) {
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001258 EXPECT_TRUE(service_->remote_certification_[i].empty());
Paul Stewartbc6e7392012-05-24 07:07:48 -07001259 }
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001260 EXPECT_EQ(kSubject, service_->remote_certification_[
Paul Stewartbc6e7392012-05-24 07:07:48 -07001261 Service::kEAPMaxCertificationElements - 1]);
1262
1263 // Re-adding the same name in the same position should not generate a log.
1264 EXPECT_CALL(log, Log(_, _, _)).Times(0);
1265 EXPECT_TRUE(service_->AddEAPCertification(
1266 kSubject, Service::kEAPMaxCertificationElements - 1));
1267
1268 // Replacing the item should generate a log message.
1269 EXPECT_CALL(log,
1270 Log(logging::LOG_INFO, _, HasSubstr("Received certification")))
1271 .Times(1);
1272 EXPECT_TRUE(service_->AddEAPCertification(
1273 kSubject + "x", Service::kEAPMaxCertificationElements - 1));
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001274
1275 service_->ClearEAPCertification();
1276 EXPECT_TRUE(service_->remote_certification_.empty());
Paul Stewartbc6e7392012-05-24 07:07:48 -07001277}
1278
Darin Petkovc8d91e52013-01-21 11:43:47 +01001279TEST_F(ServiceTest, NoteDisconnectEventIdle) {
Paul Stewart483e4722012-12-18 10:23:17 -08001280 Timestamp timestamp;
Darin Petkovc8d91e52013-01-21 11:43:47 +01001281 EXPECT_CALL(time_, GetNow()).Times(4).WillRepeatedly((Return(timestamp)));
Darin Petkov385b9bc2012-12-03 15:25:05 +01001282 SetStateField(Service::kStateOnline);
Darin Petkov0857f8e2012-12-21 10:49:17 +01001283 EXPECT_FALSE(service_->HasRecentConnectionIssues());
Darin Petkov385b9bc2012-12-03 15:25:05 +01001284 service_->SetState(Service::kStateIdle);
Darin Petkovc8d91e52013-01-21 11:43:47 +01001285 // The transition Online->Idle is not an event.
Darin Petkov0857f8e2012-12-21 10:49:17 +01001286 EXPECT_FALSE(service_->HasRecentConnectionIssues());
Darin Petkovc8d91e52013-01-21 11:43:47 +01001287 service_->SetState(Service::kStateFailure);
1288 // The transition Online->Idle->Failure is a connection drop.
1289 EXPECT_TRUE(service_->HasRecentConnectionIssues());
Darin Petkov0857f8e2012-12-21 10:49:17 +01001290}
1291
1292TEST_F(ServiceTest, NoteDisconnectEventOnSetStateFailure) {
1293 Timestamp timestamp;
1294 EXPECT_CALL(time_, GetNow()).Times(3).WillRepeatedly((Return(timestamp)));
1295 SetStateField(Service::kStateOnline);
1296 EXPECT_FALSE(service_->HasRecentConnectionIssues());
1297 service_->SetState(Service::kStateFailure);
1298 EXPECT_TRUE(service_->HasRecentConnectionIssues());
1299}
1300
1301TEST_F(ServiceTest, NoteDisconnectEventOnSetFailureSilent) {
1302 Timestamp timestamp;
1303 EXPECT_CALL(time_, GetNow()).Times(3).WillRepeatedly((Return(timestamp)));
1304 SetStateField(Service::kStateConfiguring);
1305 EXPECT_FALSE(service_->HasRecentConnectionIssues());
1306 service_->SetFailureSilent(Service::kFailureEAPAuthentication);
Paul Stewart483e4722012-12-18 10:23:17 -08001307 EXPECT_TRUE(service_->HasRecentConnectionIssues());
Darin Petkov385b9bc2012-12-03 15:25:05 +01001308}
1309
1310TEST_F(ServiceTest, NoteDisconnectEventNonEvent) {
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001311 EXPECT_CALL(time_, GetNow()).Times(0);
Darin Petkov385b9bc2012-12-03 15:25:05 +01001312 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(0);
1313
1314 // Explicit disconnect is a non-event.
1315 SetStateField(Service::kStateOnline);
1316 SetExplicitlyDisconnected(true);
1317 NoteDisconnectEvent();
1318 EXPECT_TRUE(GetDisconnects()->empty());
1319 EXPECT_TRUE(GetMisconnects()->empty());
1320
1321 // Failure to idle transition is a non-event.
1322 SetStateField(Service::kStateFailure);
1323 SetExplicitlyDisconnected(false);
1324 NoteDisconnectEvent();
1325 EXPECT_TRUE(GetDisconnects()->empty());
1326 EXPECT_TRUE(GetMisconnects()->empty());
Darin Petkovcb0b5662012-12-13 09:59:44 +01001327
1328 // Disconnect while manager is stopped is a non-event.
1329 SetStateField(Service::kStateOnline);
1330 SetManagerRunning(false);
1331 NoteDisconnectEvent();
1332 EXPECT_TRUE(GetDisconnects()->empty());
1333 EXPECT_TRUE(GetMisconnects()->empty());
1334
1335 // Disconnect while suspending is a non-event.
1336 SetManagerRunning(true);
1337 SetPowerState(PowerManager::kSuspending);
1338 NoteDisconnectEvent();
1339 EXPECT_TRUE(GetDisconnects()->empty());
1340 EXPECT_TRUE(GetMisconnects()->empty());
Darin Petkov385b9bc2012-12-03 15:25:05 +01001341}
1342
1343TEST_F(ServiceTest, NoteDisconnectEventDisconnectOnce) {
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001344 const int kNow = 5;
Darin Petkov385b9bc2012-12-03 15:25:05 +01001345 EXPECT_FALSE(service_->explicitly_disconnected());
1346 SetStateField(Service::kStateOnline);
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001347 EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(kNow, "")));
Darin Petkov385b9bc2012-12-03 15:25:05 +01001348 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(0);
1349 NoteDisconnectEvent();
1350 ASSERT_EQ(1, GetDisconnects()->size());
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001351 EXPECT_EQ(kNow, GetDisconnects()->front().monotonic.tv_sec);
Darin Petkov385b9bc2012-12-03 15:25:05 +01001352 EXPECT_TRUE(GetMisconnects()->empty());
Paul Stewart483e4722012-12-18 10:23:17 -08001353
1354 Mock::VerifyAndClearExpectations(&time_);
1355 EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(
1356 kNow + GetDisconnectsMonitorSeconds() - 1, "")));
1357 EXPECT_TRUE(service_->HasRecentConnectionIssues());
1358 ASSERT_EQ(1, GetDisconnects()->size());
1359
1360 Mock::VerifyAndClearExpectations(&time_);
1361 EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(
1362 kNow + GetDisconnectsMonitorSeconds(), "")));
1363 EXPECT_FALSE(service_->HasRecentConnectionIssues());
1364 ASSERT_TRUE(GetDisconnects()->empty());
Darin Petkov385b9bc2012-12-03 15:25:05 +01001365}
1366
1367TEST_F(ServiceTest, NoteDisconnectEventDisconnectThreshold) {
1368 EXPECT_FALSE(service_->explicitly_disconnected());
1369 SetStateField(Service::kStateOnline);
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001370 const int kNow = 6;
Darin Petkov385b9bc2012-12-03 15:25:05 +01001371 for (int i = 0; i < GetReportDisconnectsThreshold() - 1; i++) {
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001372 PushTimestamp(GetDisconnects(), kNow, "");
Darin Petkov385b9bc2012-12-03 15:25:05 +01001373 }
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001374 EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(kNow, "")));
Darin Petkov385b9bc2012-12-03 15:25:05 +01001375 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(1);
1376 NoteDisconnectEvent();
1377 EXPECT_EQ(GetReportDisconnectsThreshold(), GetDisconnects()->size());
1378}
1379
1380TEST_F(ServiceTest, NoteDisconnectEventMisconnectOnce) {
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001381 const int kNow = 7;
Darin Petkov385b9bc2012-12-03 15:25:05 +01001382 EXPECT_FALSE(service_->explicitly_disconnected());
1383 SetStateField(Service::kStateConfiguring);
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001384 EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(kNow, "")));
Darin Petkov385b9bc2012-12-03 15:25:05 +01001385 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(0);
1386 NoteDisconnectEvent();
1387 EXPECT_TRUE(GetDisconnects()->empty());
1388 ASSERT_EQ(1, GetMisconnects()->size());
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001389 EXPECT_EQ(kNow, GetMisconnects()->front().monotonic.tv_sec);
Paul Stewart483e4722012-12-18 10:23:17 -08001390
1391 Mock::VerifyAndClearExpectations(&time_);
1392 EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(
1393 kNow + GetMisconnectsMonitorSeconds() - 1, "")));
1394 EXPECT_TRUE(service_->HasRecentConnectionIssues());
1395 ASSERT_EQ(1, GetMisconnects()->size());
1396
1397 Mock::VerifyAndClearExpectations(&time_);
1398 EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(
1399 kNow + GetMisconnectsMonitorSeconds(), "")));
1400 EXPECT_FALSE(service_->HasRecentConnectionIssues());
1401 ASSERT_TRUE(GetMisconnects()->empty());
Darin Petkov385b9bc2012-12-03 15:25:05 +01001402}
1403
1404TEST_F(ServiceTest, NoteDisconnectEventMisconnectThreshold) {
1405 EXPECT_FALSE(service_->explicitly_disconnected());
1406 SetStateField(Service::kStateConfiguring);
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001407 const int kNow = 8;
Darin Petkov385b9bc2012-12-03 15:25:05 +01001408 for (int i = 0; i < GetReportMisconnectsThreshold() - 1; i++) {
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001409 PushTimestamp(GetMisconnects(), kNow, "");
Darin Petkov385b9bc2012-12-03 15:25:05 +01001410 }
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001411 EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(kNow, "")));
Darin Petkov385b9bc2012-12-03 15:25:05 +01001412 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(1);
1413 NoteDisconnectEvent();
1414 EXPECT_EQ(GetReportMisconnectsThreshold(), GetMisconnects()->size());
1415}
1416
1417TEST_F(ServiceTest, NoteDisconnectEventDiscardOld) {
1418 EXPECT_FALSE(service_->explicitly_disconnected());
1419 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(0);
1420 for (int i = 0; i < 2; i++) {
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001421 int now = 0;
1422 deque<Timestamp> *events = NULL;
Darin Petkov385b9bc2012-12-03 15:25:05 +01001423 if (i == 0) {
1424 SetStateField(Service::kStateConnected);
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001425 now = GetDisconnectsMonitorSeconds() + 1;
Darin Petkov385b9bc2012-12-03 15:25:05 +01001426 events = GetDisconnects();
1427 } else {
1428 SetStateField(Service::kStateAssociating);
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001429 now = GetMisconnectsMonitorSeconds() + 1;
Darin Petkov385b9bc2012-12-03 15:25:05 +01001430 events = GetMisconnects();
1431 }
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001432 PushTimestamp(events, 0, "");
1433 PushTimestamp(events, 0, "");
1434 EXPECT_CALL(time_, GetNow()).WillOnce(Return(GetTimestamp(now, "")));
Darin Petkov385b9bc2012-12-03 15:25:05 +01001435 NoteDisconnectEvent();
1436 ASSERT_EQ(1, events->size());
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001437 EXPECT_EQ(now, events->front().monotonic.tv_sec);
Darin Petkov385b9bc2012-12-03 15:25:05 +01001438 }
1439}
1440
1441TEST_F(ServiceTest, NoteDisconnectEventDiscardExcessive) {
1442 EXPECT_FALSE(service_->explicitly_disconnected());
1443 SetStateField(Service::kStateOnline);
Darin Petkov385b9bc2012-12-03 15:25:05 +01001444 for (int i = 0; i < 2 * GetMaxDisconnectEventHistory(); i++) {
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001445 PushTimestamp(GetDisconnects(), 0, "");
Darin Petkov385b9bc2012-12-03 15:25:05 +01001446 }
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001447 EXPECT_CALL(time_, GetNow()).WillOnce(Return(Timestamp()));
Darin Petkov385b9bc2012-12-03 15:25:05 +01001448 EXPECT_CALL(diagnostics_reporter_, OnConnectivityEvent()).Times(1);
1449 NoteDisconnectEvent();
1450 EXPECT_EQ(GetMaxDisconnectEventHistory(), GetDisconnects()->size());
1451}
1452
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001453TEST_F(ServiceTest, ConvertTimestampsToStrings) {
1454 EXPECT_TRUE(ExtractWallClockToStrings(deque<Timestamp>()).empty());
1455
1456 const Timestamp kValues[] = {
Darin Petkov0857f8e2012-12-21 10:49:17 +01001457 GetTimestamp(123, "2012-12-09T12:41:22.123456+0100"),
1458 GetTimestamp(234, "2012-12-31T23:59:59.012345+0100")
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001459 };
1460 Strings strings =
1461 ExtractWallClockToStrings(
1462 deque<Timestamp>(kValues, kValues + arraysize(kValues)));
1463 EXPECT_GT(arraysize(kValues), 0);
1464 ASSERT_EQ(arraysize(kValues), strings.size());
1465 for (size_t i = 0; i < arraysize(kValues); i++) {
1466 EXPECT_EQ(kValues[i].wall_clock, strings[i]);
1467 }
1468}
1469
1470TEST_F(ServiceTest, DiagnosticsProperties) {
Darin Petkov0857f8e2012-12-21 10:49:17 +01001471 const string kWallClock0 = "2012-12-09T12:41:22.234567-0800";
1472 const string kWallClock1 = "2012-12-31T23:59:59.345678-0800";
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001473 Strings values;
1474
1475 PushTimestamp(GetDisconnects(), 0, kWallClock0);
Paul Stewarte6e8e492013-01-17 11:00:50 -08001476 Error unused_error;
1477 ASSERT_TRUE(service_->store().GetStringsProperty(
1478 kDiagnosticsDisconnectsProperty, &values, &unused_error));
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001479 ASSERT_EQ(1, values.size());
1480 EXPECT_EQ(kWallClock0, values[0]);
1481
1482 PushTimestamp(GetMisconnects(), 0, kWallClock1);
Paul Stewarte6e8e492013-01-17 11:00:50 -08001483 ASSERT_TRUE(service_->store().GetStringsProperty(
1484 kDiagnosticsMisconnectsProperty, &values, &unused_error));
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001485 ASSERT_EQ(1, values.size());
1486 EXPECT_EQ(kWallClock1, values[0]);
1487}
1488
mukesh agrawal43970a22013-02-15 16:00:07 -08001489TEST_F(ServiceTest, SecurityLevel) {
1490 // Encrypted is better than not.
1491 service_->SetSecurity(Service::kCryptoNone, false, false);
1492 service2_->SetSecurity(Service::kCryptoRc4, false, false);
1493 EXPECT_GT(service2_->SecurityLevel(), service_->SecurityLevel());
1494
1495 // AES encryption is better than RC4 encryption.
1496 service_->SetSecurity(Service::kCryptoRc4, false, false);
1497 service2_->SetSecurity(Service::kCryptoAes, false, false);
1498 EXPECT_GT(service2_->SecurityLevel(), service_->SecurityLevel());
1499
1500 // Crypto algorithm is more important than key rotation.
1501 service_->SetSecurity(Service::kCryptoNone, true, false);
1502 service2_->SetSecurity(Service::kCryptoAes, false, false);
1503 EXPECT_GT(service2_->SecurityLevel(), service_->SecurityLevel());
1504
1505 // Encrypted-but-unauthenticated is better than clear-but-authenticated.
1506 service_->SetSecurity(Service::kCryptoNone, false, true);
1507 service2_->SetSecurity(Service::kCryptoAes, false, false);
1508 EXPECT_GT(service2_->SecurityLevel(), service_->SecurityLevel());
1509
1510 // For same encryption, prefer key rotation.
1511 service_->SetSecurity(Service::kCryptoRc4, false, false);
1512 service2_->SetSecurity(Service::kCryptoRc4, true, false);
1513 EXPECT_GT(service2_->SecurityLevel(), service_->SecurityLevel());
1514
1515 // For same encryption, prefer authenticated AP.
1516 service_->SetSecurity(Service::kCryptoRc4, false, false);
1517 service2_->SetSecurity(Service::kCryptoRc4, false, true);
1518 EXPECT_GT(service2_->SecurityLevel(), service_->SecurityLevel());
1519}
1520
Darin Petkovaba89322013-03-11 14:48:22 +01001521TEST_F(ServiceTest, SetErrorDetails) {
1522 EXPECT_EQ(Service::kErrorDetailsNone, service_->error_details());
1523 static const char kDetails[] = "Certificate revoked.";
1524 ServiceMockAdaptor *adaptor = GetAdaptor();
1525 EXPECT_CALL(*adaptor, EmitStringChanged(shill::kErrorDetailsProperty,
1526 kDetails));
1527 service_->SetErrorDetails(Service::kErrorDetailsNone);
1528 EXPECT_EQ(Service::kErrorDetailsNone, service_->error_details());
1529 service_->SetErrorDetails(kDetails);
1530 EXPECT_EQ(kDetails, service_->error_details());
1531 service_->SetErrorDetails(kDetails);
1532}
1533
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001534TEST_F(ServiceTest, SetAutoConnectFull) {
Darin Petkov36d962d2013-03-25 13:03:14 +01001535 EXPECT_FALSE(service_->auto_connect());
1536 Error error;
1537 EXPECT_FALSE(GetAutoConnect(&error));
1538 EXPECT_TRUE(error.IsSuccess());
1539
1540 // false -> false
1541 EXPECT_CALL(mock_manager_, UpdateService(_)).Times(0);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001542 SetAutoConnectFull(false, &error);
Darin Petkov36d962d2013-03-25 13:03:14 +01001543 EXPECT_TRUE(error.IsSuccess());
1544 EXPECT_FALSE(service_->auto_connect());
1545 EXPECT_FALSE(GetAutoConnect(NULL));
1546 Mock::VerifyAndClearExpectations(&mock_manager_);
1547
1548 // false -> true
1549 EXPECT_CALL(mock_manager_, UpdateService(_)).Times(1);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001550 SetAutoConnectFull(true, &error);
Darin Petkov36d962d2013-03-25 13:03:14 +01001551 EXPECT_TRUE(error.IsSuccess());
1552 EXPECT_TRUE(service_->auto_connect());
1553 EXPECT_TRUE(GetAutoConnect(NULL));
1554 Mock::VerifyAndClearExpectations(&mock_manager_);
1555
1556 // true -> true
1557 EXPECT_CALL(mock_manager_, UpdateService(_)).Times(0);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001558 SetAutoConnectFull(true, &error);
Darin Petkov36d962d2013-03-25 13:03:14 +01001559 EXPECT_TRUE(error.IsSuccess());
1560 EXPECT_TRUE(service_->auto_connect());
1561 EXPECT_TRUE(GetAutoConnect(NULL));
1562 Mock::VerifyAndClearExpectations(&mock_manager_);
1563
1564 // true -> false
1565 EXPECT_CALL(mock_manager_, UpdateService(_)).Times(1);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001566 SetAutoConnectFull(false, &error);
Darin Petkov36d962d2013-03-25 13:03:14 +01001567 EXPECT_TRUE(error.IsSuccess());
1568 EXPECT_FALSE(service_->auto_connect());
1569 EXPECT_FALSE(GetAutoConnect(NULL));
1570 Mock::VerifyAndClearExpectations(&mock_manager_);
1571}
1572
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001573TEST_F(ServiceTest, PropertyChanges) {
1574 TestCommonPropertyChanges(service_, GetAdaptor());
1575 TestAutoConnectPropertyChange(service_, GetAdaptor());
1576}
1577
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001578// Custom property setters should return false, and make no changes, if
1579// the new value is the same as the old value.
1580TEST_F(ServiceTest, CustomSetterNoopChange) {
1581 TestCustomSetterNoopChange(service_, &mock_manager_);
1582}
1583
Chris Masone3bd3c8c2011-06-13 08:20:26 -07001584} // namespace shill