blob: 3fb5d26bbf225668cc9ec9463b02db1cc11563c7 [file] [log] [blame]
Paul Stewartd8ad3c42012-01-09 12:39:38 -08001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Chris Masone3bd3c8c2011-06-13 08:20:26 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/service.h"
6
7#include <map>
8#include <string>
9#include <vector>
10
Eric Shienbrood9a245532012-03-07 14:20:39 -050011#include <base/bind.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070012#include <chromeos/dbus/service_constants.h>
mukesh agrawal1830fa12011-09-26 14:31:40 -070013#include <dbus-c++/dbus.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070014#include <gtest/gtest.h>
15#include <gmock/gmock.h>
16
17#include "shill/dbus_adaptor.h"
18#include "shill/ethernet_service.h"
Paul Stewart26b327e2011-10-19 11:38:09 -070019#include "shill/event_dispatcher.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070020#include "shill/manager.h"
Chris Masone95207da2011-06-29 16:50:49 -070021#include "shill/mock_adaptors.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070022#include "shill/mock_control.h"
Paul Stewart10241e32012-04-23 18:15:06 -070023#include "shill/mock_connection.h"
24#include "shill/mock_device_info.h"
Paul Stewart03dba0b2011-08-22 16:32:45 -070025#include "shill/mock_manager.h"
Paul Stewartff14b022012-04-24 20:06:23 -070026#include "shill/mock_profile.h"
Darin Petkovba40dd32011-07-11 20:06:39 -070027#include "shill/mock_store.h"
Paul Stewart8e7e4592012-04-29 09:47:48 -070028#include "shill/property_store_inspector.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070029#include "shill/property_store_unittest.h"
Chris Masone6515aab2011-10-12 16:19:09 -070030#include "shill/service_under_test.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070031
Eric Shienbrood9a245532012-03-07 14:20:39 -050032using base::Bind;
33using base::Unretained;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070034using std::map;
35using std::string;
36using std::vector;
Darin Petkovba40dd32011-07-11 20:06:39 -070037using testing::_;
mukesh agrawalcf24a242012-05-21 16:46:11 -070038using testing::AnyNumber;
Darin Petkovba40dd32011-07-11 20:06:39 -070039using testing::AtLeast;
Paul Stewartd8ad3c42012-01-09 12:39:38 -080040using testing::DoAll;
Paul Stewart81426132012-05-16 10:05:10 -070041using testing::Mock;
Darin Petkovba40dd32011-07-11 20:06:39 -070042using testing::NiceMock;
43using testing::Return;
Paul Stewart10241e32012-04-23 18:15:06 -070044using testing::ReturnRef;
Darin Petkovba40dd32011-07-11 20:06:39 -070045using testing::StrictMock;
Paul Stewartd8ad3c42012-01-09 12:39:38 -080046using testing::SetArgumentPointee;
Darin Petkovba40dd32011-07-11 20:06:39 -070047using testing::Test;
Paul Stewart9f32d192012-01-30 20:37:50 -080048using testing::Values;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070049
50namespace shill {
51
52class ServiceTest : public PropertyStoreTest {
53 public:
Chris Masoneb925cc82011-06-22 15:39:57 -070054 ServiceTest()
Thieu Le3426c8f2012-01-11 17:35:11 -080055 : mock_manager_(control_interface(), dispatcher(), metrics(), glib()),
Chris Masone2176a882011-09-14 22:29:15 -070056 service_(new ServiceUnderTest(control_interface(),
57 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -080058 metrics(),
Paul Stewart03dba0b2011-08-22 16:32:45 -070059 &mock_manager_)),
Chris Masone9d779932011-08-25 16:33:41 -070060 storage_id_(ServiceUnderTest::kStorageId) {
61 }
Chris Masoneb925cc82011-06-22 15:39:57 -070062
Chris Masone3bd3c8c2011-06-13 08:20:26 -070063 virtual ~ServiceTest() {}
Chris Masoneb925cc82011-06-22 15:39:57 -070064
Eric Shienbrood9a245532012-03-07 14:20:39 -050065 MOCK_METHOD1(TestCallback, void(const Error &error));
66
Chris Masoneb925cc82011-06-22 15:39:57 -070067 protected:
mukesh agrawalcf24a242012-05-21 16:46:11 -070068 typedef scoped_refptr<MockProfile> MockProfileRefPtr;
Eric Shienbrood9a245532012-03-07 14:20:39 -050069
Paul Stewart03dba0b2011-08-22 16:32:45 -070070 MockManager mock_manager_;
71 scoped_refptr<ServiceUnderTest> service_;
Chris Masone34af2182011-08-22 11:59:36 -070072 string storage_id_;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070073};
74
Darin Petkovba40dd32011-07-11 20:06:39 -070075TEST_F(ServiceTest, Constructor) {
76 EXPECT_TRUE(service_->save_credentials_);
77 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -040078 EXPECT_EQ(Service::kStateIdle, service_->state());
mukesh agrawalcf24a242012-05-21 16:46:11 -070079 EXPECT_FALSE(service_->has_ever_connected());
Darin Petkovba40dd32011-07-11 20:06:39 -070080}
81
Chris Masonea8a2c252011-06-27 22:16:30 -070082TEST_F(ServiceTest, GetProperties) {
83 map<string, ::DBus::Variant> props;
84 Error error(Error::kInvalidProperty, "");
85 {
86 ::DBus::Error dbus_error;
Paul Stewartd215af62012-04-24 23:25:50 -070087 string expected("true");
mukesh agrawalde29fa82011-09-16 16:16:36 -070088 service_->mutable_store()->SetStringProperty(flimflam::kCheckPortalProperty,
89 expected,
90 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -070091 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -070092 ASSERT_FALSE(props.find(flimflam::kCheckPortalProperty) == props.end());
93 EXPECT_EQ(props[flimflam::kCheckPortalProperty].reader().get_string(),
94 expected);
95 }
96 {
97 ::DBus::Error dbus_error;
98 bool expected = true;
Thieu Le284fe792012-01-31 17:53:19 -080099 service_->set_favorite(true);
mukesh agrawalde29fa82011-09-16 16:16:36 -0700100 service_->mutable_store()->SetBoolProperty(flimflam::kAutoConnectProperty,
101 expected,
102 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700103 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700104 ASSERT_FALSE(props.find(flimflam::kAutoConnectProperty) == props.end());
105 EXPECT_EQ(props[flimflam::kAutoConnectProperty].reader().get_bool(),
106 expected);
107 }
108 {
109 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -0700110 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700111 ASSERT_FALSE(props.find(flimflam::kConnectableProperty) == props.end());
112 EXPECT_EQ(props[flimflam::kConnectableProperty].reader().get_bool(), false);
113 }
114 {
115 ::DBus::Error dbus_error;
116 int32 expected = 127;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700117 service_->mutable_store()->SetInt32Property(flimflam::kPriorityProperty,
118 expected,
119 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700120 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700121 ASSERT_FALSE(props.find(flimflam::kPriorityProperty) == props.end());
122 EXPECT_EQ(props[flimflam::kPriorityProperty].reader().get_int32(),
123 expected);
124 }
Chris Masone95207da2011-06-29 16:50:49 -0700125 {
126 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -0700127 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masone95207da2011-06-29 16:50:49 -0700128 ASSERT_FALSE(props.find(flimflam::kDeviceProperty) == props.end());
Jason Glasgowacdc11f2012-03-30 14:12:22 -0400129 EXPECT_EQ(props[flimflam::kDeviceProperty].reader().get_path(),
Paul Stewart03dba0b2011-08-22 16:32:45 -0700130 string(ServiceUnderTest::kRpcId));
Chris Masone95207da2011-06-29 16:50:49 -0700131 }
Chris Masonea8a2c252011-06-27 22:16:30 -0700132}
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700133
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800134TEST_F(ServiceTest, SetProperty) {
Chris Masonea8a2c252011-06-27 22:16:30 -0700135 {
136 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800137 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
138 flimflam::kSaveCredentialsProperty,
139 PropertyStoreTest::kBoolV,
140 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700141 }
142 {
143 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800144 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
145 flimflam::kPriorityProperty,
146 PropertyStoreTest::kInt32V,
147 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700148 }
149 {
150 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800151 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
152 flimflam::kEAPEAPProperty,
153 PropertyStoreTest::kStringV,
154 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700155 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700156 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
Chris Masonea8a2c252011-06-27 22:16:30 -0700157 {
158 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800159 EXPECT_FALSE(DBusAdaptor::SetProperty(service_->mutable_store(),
160 flimflam::kFavoriteProperty,
161 PropertyStoreTest::kBoolV,
162 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700163 EXPECT_EQ(invalid_args(), error.name());
Chris Masonea8a2c252011-06-27 22:16:30 -0700164 }
Thieu Le284fe792012-01-31 17:53:19 -0800165 {
166 ::DBus::Error error;
167 service_->set_favorite(true);
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800168 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
169 flimflam::kAutoConnectProperty,
170 PropertyStoreTest::kBoolV,
171 &error));
Thieu Le284fe792012-01-31 17:53:19 -0800172 }
173 {
174 ::DBus::Error error;
175 service_->set_favorite(false);
Wade Guthrie4f28e8b2012-04-11 10:52:07 -0700176 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800177 flimflam::kAutoConnectProperty,
178 PropertyStoreTest::kBoolV,
179 &error));
Thieu Le284fe792012-01-31 17:53:19 -0800180 }
Paul Stewart0c438332012-04-11 07:55:27 -0700181 // Ensure that we can perform a trivial set of the Name property (to its
182 // current value) but an attempt to set the property to a different value
183 // fails.
184 {
185 ::DBus::Error error;
186 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
187 flimflam::kNameProperty,
188 DBusAdaptor::StringToVariant(
189 service_->friendly_name()),
190 &error));
191 }
192 {
193 ::DBus::Error error;
194 EXPECT_FALSE(DBusAdaptor::SetProperty(service_->mutable_store(),
195 flimflam::kNameProperty,
196 PropertyStoreTest::kStringV,
197 &error));
198 EXPECT_EQ(invalid_args(), error.name());
199 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700200}
201
Darin Petkovba40dd32011-07-11 20:06:39 -0700202TEST_F(ServiceTest, Load) {
203 NiceMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700204 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
205 EXPECT_CALL(storage, GetString(storage_id_, _, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700206 .Times(AtLeast(1))
207 .WillRepeatedly(Return(true));
Chris Masone9d779932011-08-25 16:33:41 -0700208 EXPECT_TRUE(service_->Load(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700209}
210
211TEST_F(ServiceTest, LoadFail) {
212 StrictMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700213 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(false));
Chris Masone9d779932011-08-25 16:33:41 -0700214 EXPECT_FALSE(service_->Load(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700215}
216
217TEST_F(ServiceTest, SaveString) {
218 MockStore storage;
219 static const char kKey[] = "test-key";
220 static const char kData[] = "test-data";
Chris Masone34af2182011-08-22 11:59:36 -0700221 EXPECT_CALL(storage, SetString(storage_id_, kKey, kData))
Darin Petkovba40dd32011-07-11 20:06:39 -0700222 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700223 service_->SaveString(&storage, storage_id_, kKey, kData, false, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700224}
225
226TEST_F(ServiceTest, SaveStringCrypted) {
227 MockStore storage;
228 static const char kKey[] = "test-key";
229 static const char kData[] = "test-data";
Chris Masone34af2182011-08-22 11:59:36 -0700230 EXPECT_CALL(storage, SetCryptedString(storage_id_, kKey, kData))
Darin Petkovba40dd32011-07-11 20:06:39 -0700231 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700232 service_->SaveString(&storage, storage_id_, kKey, kData, true, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700233}
234
235TEST_F(ServiceTest, SaveStringDontSave) {
236 MockStore storage;
237 static const char kKey[] = "test-key";
Chris Masone34af2182011-08-22 11:59:36 -0700238 EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
Darin Petkovba40dd32011-07-11 20:06:39 -0700239 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700240 service_->SaveString(&storage, storage_id_, kKey, "data", false, false);
Darin Petkovba40dd32011-07-11 20:06:39 -0700241}
242
243TEST_F(ServiceTest, SaveStringEmpty) {
244 MockStore storage;
245 static const char kKey[] = "test-key";
Chris Masone34af2182011-08-22 11:59:36 -0700246 EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
Darin Petkovba40dd32011-07-11 20:06:39 -0700247 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700248 service_->SaveString(&storage, storage_id_, kKey, "", true, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700249}
250
251TEST_F(ServiceTest, Save) {
252 NiceMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700253 EXPECT_CALL(storage, SetString(storage_id_, _, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700254 .Times(AtLeast(1))
255 .WillRepeatedly(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700256 EXPECT_CALL(storage, DeleteKey(storage_id_, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700257 .Times(AtLeast(1))
258 .WillRepeatedly(Return(true));
Chris Masone9d779932011-08-25 16:33:41 -0700259 EXPECT_TRUE(service_->Save(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700260}
261
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800262TEST_F(ServiceTest, Unload) {
263 NiceMock<MockStore> storage;
264 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
265 static const string string_value("value");
266 EXPECT_CALL(storage, GetString(storage_id_, _, _))
267 .Times(AtLeast(1))
268 .WillRepeatedly(DoAll(SetArgumentPointee<2>(string_value), Return(true)));
269 ASSERT_TRUE(service_->Load(&storage));
270 // TODO(pstew): A single string property in the service is tested as
mukesh agrawalcf24a242012-05-21 16:46:11 -0700271 // a sentinel that properties are being set and reset at the right times.
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800272 // However, since property load/store is essentially a manual process,
273 // it is error prone and should either be exhaustively unit-tested or
274 // a generic framework for registering loaded/stored properties should
275 // be created. crosbug.com/24859
276 EXPECT_EQ(string_value, service_->ui_data_);
277 service_->Unload();
278 EXPECT_EQ(string(""), service_->ui_data_);
279}
280
Paul Stewart03dba0b2011-08-22 16:32:45 -0700281TEST_F(ServiceTest, State) {
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400282 EXPECT_EQ(Service::kStateIdle, service_->state());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700283 EXPECT_EQ(Service::kFailureUnknown, service_->failure());
284
mukesh agrawal00917ce2011-11-22 23:56:55 +0000285 ServiceRefPtr service_ref(service_);
mukesh agrawalf2f68a52011-09-01 12:15:48 -0700286
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400287 EXPECT_CALL(*dynamic_cast<ServiceMockAdaptor *>(service_->adaptor_.get()),
mukesh agrawalcf24a242012-05-21 16:46:11 -0700288 EmitStringChanged(flimflam::kStateProperty, _)).Times(7);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700289 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
290 service_->SetState(Service::kStateConnected);
291 // A second state change shouldn't cause another update
292 service_->SetState(Service::kStateConnected);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700293 EXPECT_EQ(Service::kStateConnected, service_->state());
294 EXPECT_EQ(Service::kFailureUnknown, service_->failure());
mukesh agrawalcf24a242012-05-21 16:46:11 -0700295 EXPECT_TRUE(service_->has_ever_connected_);
mukesh agrawal568b5c62012-02-28 14:44:47 -0800296
Paul Stewart03dba0b2011-08-22 16:32:45 -0700297 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
298 service_->SetState(Service::kStateDisconnected);
299
300 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
301 service_->SetFailure(Service::kFailureOutOfRange);
mukesh agrawal568b5c62012-02-28 14:44:47 -0800302 EXPECT_TRUE(service_->IsFailed());
303 EXPECT_GT(service_->failed_time_, 0);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700304 EXPECT_EQ(Service::kStateFailure, service_->state());
305 EXPECT_EQ(Service::kFailureOutOfRange, service_->failure());
mukesh agrawal568b5c62012-02-28 14:44:47 -0800306
307 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
308 service_->SetState(Service::kStateConnected);
309 EXPECT_FALSE(service_->IsFailed());
310 EXPECT_EQ(service_->failed_time_, 0);
311
312 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
313 service_->SetFailureSilent(Service::kFailurePinMissing);
314 EXPECT_TRUE(service_->IsFailed());
315 EXPECT_GT(service_->failed_time_, 0);
316 EXPECT_EQ(Service::kStateIdle, service_->state());
317 EXPECT_EQ(Service::kFailurePinMissing, service_->failure());
mukesh agrawalcf24a242012-05-21 16:46:11 -0700318
319 // If the Service has a Profile, the profile should be saved when
320 // the service enters kStateConnected. (The case where the service
321 // doesn't have a profile is tested above.)
322 MockProfileRefPtr mock_profile(
323 new MockProfile(control_interface(), &mock_manager_));
324 NiceMock<MockStore> storage;
325 service_->set_profile(mock_profile);
326 service_->has_ever_connected_ = false;
327 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
328 EXPECT_CALL(*mock_profile, GetConstStorage())
329 .WillOnce(Return(&storage));
330 EXPECT_CALL(*mock_profile, UpdateService(service_ref));
331 service_->SetState(Service::kStateConnected);
332 EXPECT_TRUE(service_->has_ever_connected_);
333 service_->set_profile(NULL); // Break reference cycle.
334
335 // Similar to the above, but emulate an emphemeral profile, which
336 // has no storage. We can't update the service in the profile, but
337 // we should not crash.
338 service_->state_ = Service::kStateIdle; // Skips state change logic.
339 service_->set_profile(mock_profile);
340 service_->has_ever_connected_ = false;
341 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
342 EXPECT_CALL(*mock_profile, GetConstStorage()).
343 WillOnce(Return(static_cast<StoreInterface *>(NULL)));
344 service_->SetState(Service::kStateConnected);
345 EXPECT_TRUE(service_->has_ever_connected_);
346 service_->set_profile(NULL); // Break reference cycle.
Paul Stewart03dba0b2011-08-22 16:32:45 -0700347}
348
Darin Petkovb100ae72011-08-24 16:19:45 -0700349TEST_F(ServiceTest, ActivateCellularModem) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500350 ResultCallback callback =
351 Bind(&ServiceTest::TestCallback, Unretained(this));
352 EXPECT_CALL(*this, TestCallback(_)).Times(0);
Darin Petkovb100ae72011-08-24 16:19:45 -0700353 Error error;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500354 service_->ActivateCellularModem("Carrier", &error, callback);
355 EXPECT_TRUE(error.IsFailure());
Darin Petkovb100ae72011-08-24 16:19:45 -0700356}
357
mukesh agrawal00917ce2011-11-22 23:56:55 +0000358TEST_F(ServiceTest, MakeFavorite) {
359 EXPECT_FALSE(service_->favorite());
360 EXPECT_FALSE(service_->auto_connect());
361
362 service_->MakeFavorite();
363 EXPECT_TRUE(service_->favorite());
364 EXPECT_TRUE(service_->auto_connect());
365}
366
367TEST_F(ServiceTest, ReMakeFavorite) {
368 service_->MakeFavorite();
369 EXPECT_TRUE(service_->favorite());
370 EXPECT_TRUE(service_->auto_connect());
371
372 service_->set_auto_connect(false);
373 service_->MakeFavorite();
374 EXPECT_TRUE(service_->favorite());
375 EXPECT_FALSE(service_->auto_connect());
376}
377
mukesh agrawal76d13882012-01-12 15:23:11 -0800378TEST_F(ServiceTest, IsAutoConnectable) {
mukesh agrawalbf14e942012-03-02 14:36:34 -0800379 const char *reason;
mukesh agrawal76d13882012-01-12 15:23:11 -0800380 service_->set_connectable(true);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800381 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawal76d13882012-01-12 15:23:11 -0800382
mukesh agrawaladb68482012-01-17 16:31:51 -0800383 // We should not auto-connect to a Service that a user has
384 // deliberately disconnected.
385 Error error;
386 service_->Disconnect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800387 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
388 EXPECT_STREQ(Service::kAutoConnExplicitDisconnect, reason);
mukesh agrawaladb68482012-01-17 16:31:51 -0800389
390 // But if the Service is reloaded, it is eligible for auto-connect
391 // again.
392 NiceMock<MockStore> storage;
393 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
394 EXPECT_TRUE(service_->Load(&storage));
mukesh agrawalbf14e942012-03-02 14:36:34 -0800395 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800396
397 // A deliberate Connect should also re-enable auto-connect.
398 service_->Disconnect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800399 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800400 service_->Connect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800401 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800402
403 // TODO(quiche): After we have resume handling in place, test that
404 // we re-enable auto-connect on resume. crosbug.com/25213
405
mukesh agrawal76d13882012-01-12 15:23:11 -0800406 service_->SetState(Service::kStateConnected);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800407 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
408 EXPECT_STREQ(Service::kAutoConnConnected, reason);
mukesh agrawal76d13882012-01-12 15:23:11 -0800409
410 service_->SetState(Service::kStateAssociating);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800411 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
412 EXPECT_STREQ(Service::kAutoConnConnecting, reason);
mukesh agrawal76d13882012-01-12 15:23:11 -0800413}
414
Paul Stewartcb59fed2012-03-21 21:14:46 -0700415TEST_F(ServiceTest, ConfigureBadProperty) {
416 KeyValueStore args;
417 args.SetString("XXXInvalid", "Value");
418 Error error;
419 service_->Configure(args, &error);
420 EXPECT_FALSE(error.IsSuccess());
421}
422
423TEST_F(ServiceTest, ConfigureBoolProperty) {
424 service_->MakeFavorite();
425 service_->set_auto_connect(false);
426 ASSERT_FALSE(service_->auto_connect());
427 KeyValueStore args;
428 args.SetBool(flimflam::kAutoConnectProperty, true);
429 Error error;
430 service_->Configure(args, &error);
431 EXPECT_TRUE(error.IsSuccess());
432 EXPECT_TRUE(service_->auto_connect());
433}
434
435TEST_F(ServiceTest, ConfigureStringProperty) {
436 const string kEAPManagement0 = "management_zero";
437 const string kEAPManagement1 = "management_one";
438 service_->SetEAPKeyManagement(kEAPManagement0);
439 ASSERT_EQ(kEAPManagement0, service_->GetEAPKeyManagement());
440 KeyValueStore args;
441 args.SetString(flimflam::kEapKeyMgmtProperty, kEAPManagement1);
442 Error error;
443 service_->Configure(args, &error);
444 EXPECT_TRUE(error.IsSuccess());
445 EXPECT_EQ(kEAPManagement1, service_->GetEAPKeyManagement());
446}
447
448TEST_F(ServiceTest, ConfigureIgnoredProperty) {
449 service_->MakeFavorite();
450 service_->set_auto_connect(false);
451 ASSERT_FALSE(service_->auto_connect());
452 KeyValueStore args;
453 args.SetBool(flimflam::kAutoConnectProperty, true);
454 Error error;
455 service_->IgnoreParameterForConfigure(flimflam::kAutoConnectProperty);
456 service_->Configure(args, &error);
457 EXPECT_TRUE(error.IsSuccess());
458 EXPECT_FALSE(service_->auto_connect());
459}
460
Paul Stewart10ccbb32012-04-26 15:59:30 -0700461TEST_F(ServiceTest, IsRemembered) {
462 ServiceConstRefPtr service_ref(service_);
463 service_->set_profile(NULL);
464 EXPECT_CALL(mock_manager_, IsServiceEphemeral(_)).Times(0);
465 EXPECT_FALSE(service_->IsRemembered());
466
467 scoped_refptr<MockProfile> profile(
468 new StrictMock<MockProfile>(control_interface(), manager()));
469 service_->set_profile(profile);
470 EXPECT_CALL(mock_manager_, IsServiceEphemeral(service_ref))
471 .WillOnce(Return(true))
472 .WillOnce(Return(false));
473 EXPECT_FALSE(service_->IsRemembered());
474 EXPECT_TRUE(service_->IsRemembered());
475}
476
Paul Stewartff14b022012-04-24 20:06:23 -0700477TEST_F(ServiceTest, OnPropertyChanged) {
478 scoped_refptr<MockProfile> profile(
479 new StrictMock<MockProfile>(control_interface(), manager()));
480 service_->set_profile(NULL);
481 // Expect no crash.
482 service_->OnPropertyChanged("");
483
484 // Expect no call to Update if the profile has no storage.
485 service_->set_profile(profile);
486 EXPECT_CALL(*profile, UpdateService(_)).Times(0);
487 EXPECT_CALL(*profile, GetConstStorage())
488 .WillOnce(Return(reinterpret_cast<StoreInterface *>(NULL)));
489 service_->OnPropertyChanged("");
490
491 // Expect call to Update if the profile has storage.
492 EXPECT_CALL(*profile, UpdateService(_)).Times(1);
493 NiceMock<MockStore> storage;
494 EXPECT_CALL(*profile, GetConstStorage()).WillOnce(Return(&storage));
495 service_->OnPropertyChanged("");
496}
497
Paul Stewartd215af62012-04-24 23:25:50 -0700498
499TEST_F(ServiceTest, RecheckPortal) {
500 ServiceRefPtr service_ref(service_);
501 service_->state_ = Service::kStateIdle;
502 EXPECT_CALL(mock_manager_, RecheckPortalOnService(_)).Times(0);
503 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
504
505 service_->state_ = Service::kStatePortal;
506 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
507 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
508
509 service_->state_ = Service::kStateConnected;
510 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
511 service_->OnPropertyChanged(flimflam::kProxyConfigProperty);
512
513 service_->state_ = Service::kStateOnline;
514 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
515 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
516
517 service_->state_ = Service::kStatePortal;
518 EXPECT_CALL(mock_manager_, RecheckPortalOnService(_)).Times(0);
519 service_->OnPropertyChanged(flimflam::kEAPKeyIDProperty);
520}
521
522TEST_F(ServiceTest, SetCheckPortal) {
523 ServiceRefPtr service_ref(service_);
524 {
525 Error error;
526 service_->SetCheckPortal("false", &error);
527 EXPECT_TRUE(error.IsSuccess());
528 EXPECT_EQ(Service::kCheckPortalFalse, service_->check_portal_);
529 }
530 {
531 Error error;
532 service_->SetCheckPortal("true", &error);
533 EXPECT_TRUE(error.IsSuccess());
534 EXPECT_EQ(Service::kCheckPortalTrue, service_->check_portal_);
535 }
536 {
537 Error error;
538 service_->SetCheckPortal("auto", &error);
539 EXPECT_TRUE(error.IsSuccess());
540 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
541 }
542 {
543 Error error;
544 service_->SetCheckPortal("xxx", &error);
545 EXPECT_FALSE(error.IsSuccess());
546 EXPECT_EQ(Error::kInvalidArguments, error.type());
547 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
548 }
549}
550
Paul Stewart9f32d192012-01-30 20:37:50 -0800551// Make sure a property is registered as a write only property
552// by reading and comparing all string properties returned on the store.
553// Subtle: We need to convert the test argument back and forth between
554// string and ::DBus::Variant because this is the parameter type that
555// our supeclass (PropertyStoreTest) is declared with.
556class ReadOnlyServicePropertyTest : public ServiceTest {};
557TEST_P(ReadOnlyServicePropertyTest, PropertyWriteOnly) {
Paul Stewart9f32d192012-01-30 20:37:50 -0800558 string property(GetParam().reader().get_string());
Paul Stewart8e7e4592012-04-29 09:47:48 -0700559 PropertyStoreInspector inspector(&service_->store());
560 EXPECT_FALSE(inspector.ContainsStringProperty(property));
Paul Stewart9f32d192012-01-30 20:37:50 -0800561}
562
563INSTANTIATE_TEST_CASE_P(
564 ReadOnlyServicePropertyTestInstance,
565 ReadOnlyServicePropertyTest,
566 Values(
567 DBusAdaptor::StringToVariant(flimflam::kEapPrivateKeyPasswordProperty),
568 DBusAdaptor::StringToVariant(flimflam::kEapPasswordProperty)));
569
Paul Stewart10241e32012-04-23 18:15:06 -0700570
571TEST_F(ServiceTest, GetIPConfigRpcIdentifier) {
572 {
573 Error error;
574 EXPECT_EQ("/", service_->GetIPConfigRpcIdentifier(&error));
575 EXPECT_EQ(Error::kNotFound, error.type());
576 }
577
578 scoped_ptr<MockDeviceInfo> mock_device_info(
579 new NiceMock<MockDeviceInfo>(control_interface(), dispatcher(), metrics(),
580 &mock_manager_));
581 scoped_refptr<MockConnection> mock_connection(
582 new NiceMock<MockConnection>(mock_device_info.get()));
583
584 service_->connection_ = mock_connection;
585
586 {
587 Error error;
588 const string empty_string;
589 EXPECT_CALL(*mock_connection, ipconfig_rpc_identifier())
590 .WillOnce(ReturnRef(empty_string));
591 EXPECT_EQ("/", service_->GetIPConfigRpcIdentifier(&error));
592 EXPECT_EQ(Error::kNotFound, error.type());
593 }
594
595 {
596 Error error;
597 const string nonempty_string("/ipconfig/path");
598 EXPECT_CALL(*mock_connection, ipconfig_rpc_identifier())
599 .WillOnce(ReturnRef(nonempty_string));
600 EXPECT_EQ(nonempty_string, service_->GetIPConfigRpcIdentifier(&error));
601 EXPECT_EQ(Error::kSuccess, error.type());
602 }
603
604 // Assure orderly destruction of the Connection before DeviceInfo.
605 service_->connection_ = NULL;
606 mock_connection = NULL;
607 mock_device_info.reset();
608}
609
Paul Stewart81426132012-05-16 10:05:10 -0700610class ServiceWithMockSetEap : public ServiceUnderTest {
611 public:
612 ServiceWithMockSetEap(ControlInterface *control_interface,
613 EventDispatcher *dispatcher,
614 Metrics *metrics,
615 Manager *manager)
616 : ServiceUnderTest(control_interface, dispatcher, metrics, manager),
617 is_8021x_(false) {}
618 MOCK_METHOD1(set_eap, void(const EapCredentials &eap));
619 virtual bool Is8021x() const { return is_8021x_; }
620 void set_is_8021x(bool is_8021x) { is_8021x_ = is_8021x; }
621
622 private:
623 bool is_8021x_;
624};
625
626TEST_F(ServiceTest, SetEAPCredentialsOverRPC) {
627 scoped_refptr<ServiceWithMockSetEap> service(
628 new ServiceWithMockSetEap(control_interface(),
629 dispatcher(),
630 metrics(),
631 &mock_manager_));
632 string eap_credential_properties[] = {
633 flimflam::kEAPCertIDProperty,
634 flimflam::kEAPClientCertProperty,
635 flimflam::kEAPKeyIDProperty,
636 flimflam::kEAPPINProperty,
637 flimflam::kEapCaCertIDProperty,
638 flimflam::kEapIdentityProperty,
639 flimflam::kEapPasswordProperty,
640 flimflam::kEapPrivateKeyProperty
641 };
642 string eap_non_credential_properties[] = {
643 flimflam::kEAPEAPProperty,
644 flimflam::kEapPhase2AuthProperty,
645 flimflam::kEapAnonymousIdentityProperty,
646 flimflam::kEapPrivateKeyPasswordProperty,
647 flimflam::kEapKeyMgmtProperty,
648 flimflam::kEapCaCertNssProperty,
649 flimflam::kEapUseSystemCAsProperty
650 };
651 // While this is not an 802.1x-based service, none of these property
652 // changes should cause a call to set_eap().
653 EXPECT_CALL(*service, set_eap(_)).Times(0);
654 for (size_t i = 0; i < arraysize(eap_credential_properties); ++i)
655 service->OnPropertyChanged(eap_credential_properties[i]);
656 for (size_t i = 0; i < arraysize(eap_non_credential_properties); ++i)
657 service->OnPropertyChanged(eap_non_credential_properties[i]);
658
659 service->set_is_8021x(true);
660
661 // When this is an 802.1x-based service, set_eap should be called for
662 // all credential-carrying properties.
663 for (size_t i = 0; i < arraysize(eap_credential_properties); ++i) {
664 EXPECT_CALL(*service, set_eap(_)).Times(1);
665 service->OnPropertyChanged(eap_credential_properties[i]);
666 Mock::VerifyAndClearExpectations(service.get());
667 }
668 EXPECT_CALL(*service, set_eap(_)).Times(0);
669 for (size_t i = 0; i < arraysize(eap_non_credential_properties); ++i)
670 service->OnPropertyChanged(eap_non_credential_properties[i]);
671}
672
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700673} // namespace shill