blob: 2f17f1219c2e9e4475ea83269f8f992fd645c880 [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 Stewartbc6e7392012-05-24 07:07:48 -070025#include "shill/mock_log.h"
Paul Stewart03dba0b2011-08-22 16:32:45 -070026#include "shill/mock_manager.h"
Paul Stewartff14b022012-04-24 20:06:23 -070027#include "shill/mock_profile.h"
Darin Petkovba40dd32011-07-11 20:06:39 -070028#include "shill/mock_store.h"
Paul Stewart8e7e4592012-04-29 09:47:48 -070029#include "shill/property_store_inspector.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070030#include "shill/property_store_unittest.h"
Chris Masone6515aab2011-10-12 16:19:09 -070031#include "shill/service_under_test.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070032
Eric Shienbrood9a245532012-03-07 14:20:39 -050033using base::Bind;
34using base::Unretained;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070035using std::map;
36using std::string;
37using std::vector;
Darin Petkovba40dd32011-07-11 20:06:39 -070038using testing::_;
mukesh agrawalcf24a242012-05-21 16:46:11 -070039using testing::AnyNumber;
Darin Petkovba40dd32011-07-11 20:06:39 -070040using testing::AtLeast;
Paul Stewartd8ad3c42012-01-09 12:39:38 -080041using testing::DoAll;
Paul Stewartbc6e7392012-05-24 07:07:48 -070042using testing::HasSubstr;
Paul Stewart81426132012-05-16 10:05:10 -070043using testing::Mock;
Darin Petkovba40dd32011-07-11 20:06:39 -070044using testing::NiceMock;
45using testing::Return;
Paul Stewart10241e32012-04-23 18:15:06 -070046using testing::ReturnRef;
Darin Petkovba40dd32011-07-11 20:06:39 -070047using testing::StrictMock;
Paul Stewartd8ad3c42012-01-09 12:39:38 -080048using testing::SetArgumentPointee;
Darin Petkovba40dd32011-07-11 20:06:39 -070049using testing::Test;
Paul Stewart9f32d192012-01-30 20:37:50 -080050using testing::Values;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070051
52namespace shill {
53
54class ServiceTest : public PropertyStoreTest {
55 public:
Chris Masoneb925cc82011-06-22 15:39:57 -070056 ServiceTest()
Thieu Le3426c8f2012-01-11 17:35:11 -080057 : mock_manager_(control_interface(), dispatcher(), metrics(), glib()),
Chris Masone2176a882011-09-14 22:29:15 -070058 service_(new ServiceUnderTest(control_interface(),
59 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -080060 metrics(),
Paul Stewart03dba0b2011-08-22 16:32:45 -070061 &mock_manager_)),
Chris Masone9d779932011-08-25 16:33:41 -070062 storage_id_(ServiceUnderTest::kStorageId) {
63 }
Chris Masoneb925cc82011-06-22 15:39:57 -070064
Chris Masone3bd3c8c2011-06-13 08:20:26 -070065 virtual ~ServiceTest() {}
Chris Masoneb925cc82011-06-22 15:39:57 -070066
Eric Shienbrood9a245532012-03-07 14:20:39 -050067 MOCK_METHOD1(TestCallback, void(const Error &error));
68
Chris Masoneb925cc82011-06-22 15:39:57 -070069 protected:
mukesh agrawalcf24a242012-05-21 16:46:11 -070070 typedef scoped_refptr<MockProfile> MockProfileRefPtr;
Eric Shienbrood9a245532012-03-07 14:20:39 -050071
Paul Stewart03dba0b2011-08-22 16:32:45 -070072 MockManager mock_manager_;
73 scoped_refptr<ServiceUnderTest> service_;
Chris Masone34af2182011-08-22 11:59:36 -070074 string storage_id_;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070075};
76
Darin Petkovba40dd32011-07-11 20:06:39 -070077TEST_F(ServiceTest, Constructor) {
78 EXPECT_TRUE(service_->save_credentials_);
79 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -040080 EXPECT_EQ(Service::kStateIdle, service_->state());
mukesh agrawalcf24a242012-05-21 16:46:11 -070081 EXPECT_FALSE(service_->has_ever_connected());
Darin Petkovba40dd32011-07-11 20:06:39 -070082}
83
Chris Masonea8a2c252011-06-27 22:16:30 -070084TEST_F(ServiceTest, GetProperties) {
85 map<string, ::DBus::Variant> props;
86 Error error(Error::kInvalidProperty, "");
87 {
88 ::DBus::Error dbus_error;
Paul Stewartd215af62012-04-24 23:25:50 -070089 string expected("true");
mukesh agrawalde29fa82011-09-16 16:16:36 -070090 service_->mutable_store()->SetStringProperty(flimflam::kCheckPortalProperty,
91 expected,
92 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -070093 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -070094 ASSERT_FALSE(props.find(flimflam::kCheckPortalProperty) == props.end());
95 EXPECT_EQ(props[flimflam::kCheckPortalProperty].reader().get_string(),
96 expected);
97 }
98 {
99 ::DBus::Error dbus_error;
100 bool expected = true;
Thieu Le284fe792012-01-31 17:53:19 -0800101 service_->set_favorite(true);
mukesh agrawalde29fa82011-09-16 16:16:36 -0700102 service_->mutable_store()->SetBoolProperty(flimflam::kAutoConnectProperty,
103 expected,
104 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700105 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700106 ASSERT_FALSE(props.find(flimflam::kAutoConnectProperty) == props.end());
107 EXPECT_EQ(props[flimflam::kAutoConnectProperty].reader().get_bool(),
108 expected);
109 }
110 {
111 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -0700112 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700113 ASSERT_FALSE(props.find(flimflam::kConnectableProperty) == props.end());
114 EXPECT_EQ(props[flimflam::kConnectableProperty].reader().get_bool(), false);
115 }
116 {
117 ::DBus::Error dbus_error;
118 int32 expected = 127;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700119 service_->mutable_store()->SetInt32Property(flimflam::kPriorityProperty,
120 expected,
121 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700122 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700123 ASSERT_FALSE(props.find(flimflam::kPriorityProperty) == props.end());
124 EXPECT_EQ(props[flimflam::kPriorityProperty].reader().get_int32(),
125 expected);
126 }
Chris Masone95207da2011-06-29 16:50:49 -0700127 {
128 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -0700129 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masone95207da2011-06-29 16:50:49 -0700130 ASSERT_FALSE(props.find(flimflam::kDeviceProperty) == props.end());
Jason Glasgowacdc11f2012-03-30 14:12:22 -0400131 EXPECT_EQ(props[flimflam::kDeviceProperty].reader().get_path(),
Paul Stewart03dba0b2011-08-22 16:32:45 -0700132 string(ServiceUnderTest::kRpcId));
Chris Masone95207da2011-06-29 16:50:49 -0700133 }
Chris Masonea8a2c252011-06-27 22:16:30 -0700134}
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700135
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800136TEST_F(ServiceTest, SetProperty) {
Chris Masonea8a2c252011-06-27 22:16:30 -0700137 {
138 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800139 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
140 flimflam::kSaveCredentialsProperty,
141 PropertyStoreTest::kBoolV,
142 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700143 }
144 {
145 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800146 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
147 flimflam::kPriorityProperty,
148 PropertyStoreTest::kInt32V,
149 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700150 }
151 {
152 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800153 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
154 flimflam::kEAPEAPProperty,
155 PropertyStoreTest::kStringV,
156 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700157 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700158 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
Chris Masonea8a2c252011-06-27 22:16:30 -0700159 {
160 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800161 EXPECT_FALSE(DBusAdaptor::SetProperty(service_->mutable_store(),
162 flimflam::kFavoriteProperty,
163 PropertyStoreTest::kBoolV,
164 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700165 EXPECT_EQ(invalid_args(), error.name());
Chris Masonea8a2c252011-06-27 22:16:30 -0700166 }
Thieu Le284fe792012-01-31 17:53:19 -0800167 {
168 ::DBus::Error error;
169 service_->set_favorite(true);
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800170 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
171 flimflam::kAutoConnectProperty,
172 PropertyStoreTest::kBoolV,
173 &error));
Thieu Le284fe792012-01-31 17:53:19 -0800174 }
175 {
176 ::DBus::Error error;
177 service_->set_favorite(false);
Wade Guthrie4f28e8b2012-04-11 10:52:07 -0700178 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800179 flimflam::kAutoConnectProperty,
180 PropertyStoreTest::kBoolV,
181 &error));
Thieu Le284fe792012-01-31 17:53:19 -0800182 }
Paul Stewart0c438332012-04-11 07:55:27 -0700183 // Ensure that we can perform a trivial set of the Name property (to its
184 // current value) but an attempt to set the property to a different value
185 // fails.
186 {
187 ::DBus::Error error;
188 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
189 flimflam::kNameProperty,
190 DBusAdaptor::StringToVariant(
191 service_->friendly_name()),
192 &error));
193 }
194 {
195 ::DBus::Error error;
196 EXPECT_FALSE(DBusAdaptor::SetProperty(service_->mutable_store(),
197 flimflam::kNameProperty,
198 PropertyStoreTest::kStringV,
199 &error));
200 EXPECT_EQ(invalid_args(), error.name());
201 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700202}
203
Darin Petkovba40dd32011-07-11 20:06:39 -0700204TEST_F(ServiceTest, Load) {
205 NiceMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700206 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
207 EXPECT_CALL(storage, GetString(storage_id_, _, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700208 .Times(AtLeast(1))
209 .WillRepeatedly(Return(true));
Chris Masone9d779932011-08-25 16:33:41 -0700210 EXPECT_TRUE(service_->Load(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700211}
212
213TEST_F(ServiceTest, LoadFail) {
214 StrictMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700215 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(false));
Chris Masone9d779932011-08-25 16:33:41 -0700216 EXPECT_FALSE(service_->Load(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700217}
218
219TEST_F(ServiceTest, SaveString) {
220 MockStore storage;
221 static const char kKey[] = "test-key";
222 static const char kData[] = "test-data";
Chris Masone34af2182011-08-22 11:59:36 -0700223 EXPECT_CALL(storage, SetString(storage_id_, kKey, kData))
Darin Petkovba40dd32011-07-11 20:06:39 -0700224 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700225 service_->SaveString(&storage, storage_id_, kKey, kData, false, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700226}
227
228TEST_F(ServiceTest, SaveStringCrypted) {
229 MockStore storage;
230 static const char kKey[] = "test-key";
231 static const char kData[] = "test-data";
Chris Masone34af2182011-08-22 11:59:36 -0700232 EXPECT_CALL(storage, SetCryptedString(storage_id_, kKey, kData))
Darin Petkovba40dd32011-07-11 20:06:39 -0700233 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700234 service_->SaveString(&storage, storage_id_, kKey, kData, true, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700235}
236
237TEST_F(ServiceTest, SaveStringDontSave) {
238 MockStore storage;
239 static const char kKey[] = "test-key";
Chris Masone34af2182011-08-22 11:59:36 -0700240 EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
Darin Petkovba40dd32011-07-11 20:06:39 -0700241 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700242 service_->SaveString(&storage, storage_id_, kKey, "data", false, false);
Darin Petkovba40dd32011-07-11 20:06:39 -0700243}
244
245TEST_F(ServiceTest, SaveStringEmpty) {
246 MockStore storage;
247 static const char kKey[] = "test-key";
Chris Masone34af2182011-08-22 11:59:36 -0700248 EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
Darin Petkovba40dd32011-07-11 20:06:39 -0700249 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700250 service_->SaveString(&storage, storage_id_, kKey, "", true, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700251}
252
253TEST_F(ServiceTest, Save) {
254 NiceMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700255 EXPECT_CALL(storage, SetString(storage_id_, _, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700256 .Times(AtLeast(1))
257 .WillRepeatedly(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700258 EXPECT_CALL(storage, DeleteKey(storage_id_, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700259 .Times(AtLeast(1))
260 .WillRepeatedly(Return(true));
Chris Masone9d779932011-08-25 16:33:41 -0700261 EXPECT_TRUE(service_->Save(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700262}
263
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800264TEST_F(ServiceTest, Unload) {
265 NiceMock<MockStore> storage;
266 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
267 static const string string_value("value");
268 EXPECT_CALL(storage, GetString(storage_id_, _, _))
269 .Times(AtLeast(1))
270 .WillRepeatedly(DoAll(SetArgumentPointee<2>(string_value), Return(true)));
271 ASSERT_TRUE(service_->Load(&storage));
272 // TODO(pstew): A single string property in the service is tested as
mukesh agrawalcf24a242012-05-21 16:46:11 -0700273 // a sentinel that properties are being set and reset at the right times.
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800274 // However, since property load/store is essentially a manual process,
275 // it is error prone and should either be exhaustively unit-tested or
276 // a generic framework for registering loaded/stored properties should
277 // be created. crosbug.com/24859
278 EXPECT_EQ(string_value, service_->ui_data_);
279 service_->Unload();
280 EXPECT_EQ(string(""), service_->ui_data_);
281}
282
Paul Stewart03dba0b2011-08-22 16:32:45 -0700283TEST_F(ServiceTest, State) {
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400284 EXPECT_EQ(Service::kStateIdle, service_->state());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700285 EXPECT_EQ(Service::kFailureUnknown, service_->failure());
286
mukesh agrawal00917ce2011-11-22 23:56:55 +0000287 ServiceRefPtr service_ref(service_);
mukesh agrawalf2f68a52011-09-01 12:15:48 -0700288
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400289 EXPECT_CALL(*dynamic_cast<ServiceMockAdaptor *>(service_->adaptor_.get()),
mukesh agrawalcf24a242012-05-21 16:46:11 -0700290 EmitStringChanged(flimflam::kStateProperty, _)).Times(7);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700291 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
292 service_->SetState(Service::kStateConnected);
293 // A second state change shouldn't cause another update
294 service_->SetState(Service::kStateConnected);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700295 EXPECT_EQ(Service::kStateConnected, service_->state());
296 EXPECT_EQ(Service::kFailureUnknown, service_->failure());
mukesh agrawalcf24a242012-05-21 16:46:11 -0700297 EXPECT_TRUE(service_->has_ever_connected_);
mukesh agrawal568b5c62012-02-28 14:44:47 -0800298
Paul Stewart03dba0b2011-08-22 16:32:45 -0700299 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
300 service_->SetState(Service::kStateDisconnected);
301
302 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
303 service_->SetFailure(Service::kFailureOutOfRange);
mukesh agrawal568b5c62012-02-28 14:44:47 -0800304 EXPECT_TRUE(service_->IsFailed());
305 EXPECT_GT(service_->failed_time_, 0);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700306 EXPECT_EQ(Service::kStateFailure, service_->state());
307 EXPECT_EQ(Service::kFailureOutOfRange, service_->failure());
mukesh agrawal568b5c62012-02-28 14:44:47 -0800308
309 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
310 service_->SetState(Service::kStateConnected);
311 EXPECT_FALSE(service_->IsFailed());
312 EXPECT_EQ(service_->failed_time_, 0);
313
314 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
315 service_->SetFailureSilent(Service::kFailurePinMissing);
316 EXPECT_TRUE(service_->IsFailed());
317 EXPECT_GT(service_->failed_time_, 0);
318 EXPECT_EQ(Service::kStateIdle, service_->state());
319 EXPECT_EQ(Service::kFailurePinMissing, service_->failure());
mukesh agrawalcf24a242012-05-21 16:46:11 -0700320
321 // If the Service has a Profile, the profile should be saved when
322 // the service enters kStateConnected. (The case where the service
323 // doesn't have a profile is tested above.)
324 MockProfileRefPtr mock_profile(
325 new MockProfile(control_interface(), &mock_manager_));
326 NiceMock<MockStore> storage;
327 service_->set_profile(mock_profile);
328 service_->has_ever_connected_ = false;
329 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
330 EXPECT_CALL(*mock_profile, GetConstStorage())
331 .WillOnce(Return(&storage));
332 EXPECT_CALL(*mock_profile, UpdateService(service_ref));
333 service_->SetState(Service::kStateConnected);
334 EXPECT_TRUE(service_->has_ever_connected_);
335 service_->set_profile(NULL); // Break reference cycle.
336
337 // Similar to the above, but emulate an emphemeral profile, which
338 // has no storage. We can't update the service in the profile, but
339 // we should not crash.
340 service_->state_ = Service::kStateIdle; // Skips state change logic.
341 service_->set_profile(mock_profile);
342 service_->has_ever_connected_ = false;
343 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
344 EXPECT_CALL(*mock_profile, GetConstStorage()).
345 WillOnce(Return(static_cast<StoreInterface *>(NULL)));
346 service_->SetState(Service::kStateConnected);
347 EXPECT_TRUE(service_->has_ever_connected_);
348 service_->set_profile(NULL); // Break reference cycle.
Paul Stewart03dba0b2011-08-22 16:32:45 -0700349}
350
Darin Petkovb100ae72011-08-24 16:19:45 -0700351TEST_F(ServiceTest, ActivateCellularModem) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500352 ResultCallback callback =
353 Bind(&ServiceTest::TestCallback, Unretained(this));
354 EXPECT_CALL(*this, TestCallback(_)).Times(0);
Darin Petkovb100ae72011-08-24 16:19:45 -0700355 Error error;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500356 service_->ActivateCellularModem("Carrier", &error, callback);
357 EXPECT_TRUE(error.IsFailure());
Darin Petkovb100ae72011-08-24 16:19:45 -0700358}
359
mukesh agrawal00917ce2011-11-22 23:56:55 +0000360TEST_F(ServiceTest, MakeFavorite) {
361 EXPECT_FALSE(service_->favorite());
362 EXPECT_FALSE(service_->auto_connect());
363
364 service_->MakeFavorite();
365 EXPECT_TRUE(service_->favorite());
366 EXPECT_TRUE(service_->auto_connect());
367}
368
369TEST_F(ServiceTest, ReMakeFavorite) {
370 service_->MakeFavorite();
371 EXPECT_TRUE(service_->favorite());
372 EXPECT_TRUE(service_->auto_connect());
373
374 service_->set_auto_connect(false);
375 service_->MakeFavorite();
376 EXPECT_TRUE(service_->favorite());
377 EXPECT_FALSE(service_->auto_connect());
378}
379
mukesh agrawal76d13882012-01-12 15:23:11 -0800380TEST_F(ServiceTest, IsAutoConnectable) {
mukesh agrawalbf14e942012-03-02 14:36:34 -0800381 const char *reason;
mukesh agrawal76d13882012-01-12 15:23:11 -0800382 service_->set_connectable(true);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800383 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawal76d13882012-01-12 15:23:11 -0800384
mukesh agrawaladb68482012-01-17 16:31:51 -0800385 // We should not auto-connect to a Service that a user has
386 // deliberately disconnected.
387 Error error;
388 service_->Disconnect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800389 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
390 EXPECT_STREQ(Service::kAutoConnExplicitDisconnect, reason);
mukesh agrawaladb68482012-01-17 16:31:51 -0800391
392 // But if the Service is reloaded, it is eligible for auto-connect
393 // again.
394 NiceMock<MockStore> storage;
395 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
396 EXPECT_TRUE(service_->Load(&storage));
mukesh agrawalbf14e942012-03-02 14:36:34 -0800397 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800398
399 // A deliberate Connect should also re-enable auto-connect.
400 service_->Disconnect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800401 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800402 service_->Connect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800403 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800404
405 // TODO(quiche): After we have resume handling in place, test that
406 // we re-enable auto-connect on resume. crosbug.com/25213
407
mukesh agrawal76d13882012-01-12 15:23:11 -0800408 service_->SetState(Service::kStateConnected);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800409 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
410 EXPECT_STREQ(Service::kAutoConnConnected, reason);
mukesh agrawal76d13882012-01-12 15:23:11 -0800411
412 service_->SetState(Service::kStateAssociating);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800413 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
414 EXPECT_STREQ(Service::kAutoConnConnecting, reason);
mukesh agrawal76d13882012-01-12 15:23:11 -0800415}
416
Paul Stewartcb59fed2012-03-21 21:14:46 -0700417TEST_F(ServiceTest, ConfigureBadProperty) {
418 KeyValueStore args;
419 args.SetString("XXXInvalid", "Value");
420 Error error;
421 service_->Configure(args, &error);
422 EXPECT_FALSE(error.IsSuccess());
423}
424
425TEST_F(ServiceTest, ConfigureBoolProperty) {
426 service_->MakeFavorite();
427 service_->set_auto_connect(false);
428 ASSERT_FALSE(service_->auto_connect());
429 KeyValueStore args;
430 args.SetBool(flimflam::kAutoConnectProperty, true);
431 Error error;
432 service_->Configure(args, &error);
433 EXPECT_TRUE(error.IsSuccess());
434 EXPECT_TRUE(service_->auto_connect());
435}
436
437TEST_F(ServiceTest, ConfigureStringProperty) {
438 const string kEAPManagement0 = "management_zero";
439 const string kEAPManagement1 = "management_one";
440 service_->SetEAPKeyManagement(kEAPManagement0);
441 ASSERT_EQ(kEAPManagement0, service_->GetEAPKeyManagement());
442 KeyValueStore args;
443 args.SetString(flimflam::kEapKeyMgmtProperty, kEAPManagement1);
444 Error error;
445 service_->Configure(args, &error);
446 EXPECT_TRUE(error.IsSuccess());
447 EXPECT_EQ(kEAPManagement1, service_->GetEAPKeyManagement());
448}
449
450TEST_F(ServiceTest, ConfigureIgnoredProperty) {
451 service_->MakeFavorite();
452 service_->set_auto_connect(false);
453 ASSERT_FALSE(service_->auto_connect());
454 KeyValueStore args;
455 args.SetBool(flimflam::kAutoConnectProperty, true);
456 Error error;
457 service_->IgnoreParameterForConfigure(flimflam::kAutoConnectProperty);
458 service_->Configure(args, &error);
459 EXPECT_TRUE(error.IsSuccess());
460 EXPECT_FALSE(service_->auto_connect());
461}
462
Paul Stewart10ccbb32012-04-26 15:59:30 -0700463TEST_F(ServiceTest, IsRemembered) {
464 ServiceConstRefPtr service_ref(service_);
465 service_->set_profile(NULL);
466 EXPECT_CALL(mock_manager_, IsServiceEphemeral(_)).Times(0);
467 EXPECT_FALSE(service_->IsRemembered());
468
469 scoped_refptr<MockProfile> profile(
470 new StrictMock<MockProfile>(control_interface(), manager()));
471 service_->set_profile(profile);
472 EXPECT_CALL(mock_manager_, IsServiceEphemeral(service_ref))
473 .WillOnce(Return(true))
474 .WillOnce(Return(false));
475 EXPECT_FALSE(service_->IsRemembered());
476 EXPECT_TRUE(service_->IsRemembered());
477}
478
Paul Stewartff14b022012-04-24 20:06:23 -0700479TEST_F(ServiceTest, OnPropertyChanged) {
480 scoped_refptr<MockProfile> profile(
481 new StrictMock<MockProfile>(control_interface(), manager()));
482 service_->set_profile(NULL);
483 // Expect no crash.
484 service_->OnPropertyChanged("");
485
486 // Expect no call to Update if the profile has no storage.
487 service_->set_profile(profile);
488 EXPECT_CALL(*profile, UpdateService(_)).Times(0);
489 EXPECT_CALL(*profile, GetConstStorage())
490 .WillOnce(Return(reinterpret_cast<StoreInterface *>(NULL)));
491 service_->OnPropertyChanged("");
492
493 // Expect call to Update if the profile has storage.
494 EXPECT_CALL(*profile, UpdateService(_)).Times(1);
495 NiceMock<MockStore> storage;
496 EXPECT_CALL(*profile, GetConstStorage()).WillOnce(Return(&storage));
497 service_->OnPropertyChanged("");
498}
499
Paul Stewartd215af62012-04-24 23:25:50 -0700500
501TEST_F(ServiceTest, RecheckPortal) {
502 ServiceRefPtr service_ref(service_);
503 service_->state_ = Service::kStateIdle;
504 EXPECT_CALL(mock_manager_, RecheckPortalOnService(_)).Times(0);
505 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
506
507 service_->state_ = Service::kStatePortal;
508 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
509 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
510
511 service_->state_ = Service::kStateConnected;
512 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
513 service_->OnPropertyChanged(flimflam::kProxyConfigProperty);
514
515 service_->state_ = Service::kStateOnline;
516 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
517 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
518
519 service_->state_ = Service::kStatePortal;
520 EXPECT_CALL(mock_manager_, RecheckPortalOnService(_)).Times(0);
521 service_->OnPropertyChanged(flimflam::kEAPKeyIDProperty);
522}
523
524TEST_F(ServiceTest, SetCheckPortal) {
525 ServiceRefPtr service_ref(service_);
526 {
527 Error error;
528 service_->SetCheckPortal("false", &error);
529 EXPECT_TRUE(error.IsSuccess());
530 EXPECT_EQ(Service::kCheckPortalFalse, service_->check_portal_);
531 }
532 {
533 Error error;
534 service_->SetCheckPortal("true", &error);
535 EXPECT_TRUE(error.IsSuccess());
536 EXPECT_EQ(Service::kCheckPortalTrue, service_->check_portal_);
537 }
538 {
539 Error error;
540 service_->SetCheckPortal("auto", &error);
541 EXPECT_TRUE(error.IsSuccess());
542 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
543 }
544 {
545 Error error;
546 service_->SetCheckPortal("xxx", &error);
547 EXPECT_FALSE(error.IsSuccess());
548 EXPECT_EQ(Error::kInvalidArguments, error.type());
549 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
550 }
551}
552
Paul Stewart9f32d192012-01-30 20:37:50 -0800553// Make sure a property is registered as a write only property
554// by reading and comparing all string properties returned on the store.
555// Subtle: We need to convert the test argument back and forth between
556// string and ::DBus::Variant because this is the parameter type that
557// our supeclass (PropertyStoreTest) is declared with.
558class ReadOnlyServicePropertyTest : public ServiceTest {};
559TEST_P(ReadOnlyServicePropertyTest, PropertyWriteOnly) {
Paul Stewart9f32d192012-01-30 20:37:50 -0800560 string property(GetParam().reader().get_string());
Paul Stewart8e7e4592012-04-29 09:47:48 -0700561 PropertyStoreInspector inspector(&service_->store());
Darin Petkov4682aa82012-05-31 16:24:11 +0200562 EXPECT_FALSE(inspector.GetStringProperty(property, NULL));
Paul Stewart9f32d192012-01-30 20:37:50 -0800563}
564
565INSTANTIATE_TEST_CASE_P(
566 ReadOnlyServicePropertyTestInstance,
567 ReadOnlyServicePropertyTest,
568 Values(
569 DBusAdaptor::StringToVariant(flimflam::kEapPrivateKeyPasswordProperty),
570 DBusAdaptor::StringToVariant(flimflam::kEapPasswordProperty)));
571
Paul Stewart10241e32012-04-23 18:15:06 -0700572
573TEST_F(ServiceTest, GetIPConfigRpcIdentifier) {
574 {
575 Error error;
576 EXPECT_EQ("/", service_->GetIPConfigRpcIdentifier(&error));
577 EXPECT_EQ(Error::kNotFound, error.type());
578 }
579
580 scoped_ptr<MockDeviceInfo> mock_device_info(
581 new NiceMock<MockDeviceInfo>(control_interface(), dispatcher(), metrics(),
582 &mock_manager_));
583 scoped_refptr<MockConnection> mock_connection(
584 new NiceMock<MockConnection>(mock_device_info.get()));
585
586 service_->connection_ = mock_connection;
587
588 {
589 Error error;
590 const string empty_string;
591 EXPECT_CALL(*mock_connection, ipconfig_rpc_identifier())
592 .WillOnce(ReturnRef(empty_string));
593 EXPECT_EQ("/", service_->GetIPConfigRpcIdentifier(&error));
594 EXPECT_EQ(Error::kNotFound, error.type());
595 }
596
597 {
598 Error error;
599 const string nonempty_string("/ipconfig/path");
600 EXPECT_CALL(*mock_connection, ipconfig_rpc_identifier())
601 .WillOnce(ReturnRef(nonempty_string));
602 EXPECT_EQ(nonempty_string, service_->GetIPConfigRpcIdentifier(&error));
603 EXPECT_EQ(Error::kSuccess, error.type());
604 }
605
606 // Assure orderly destruction of the Connection before DeviceInfo.
607 service_->connection_ = NULL;
608 mock_connection = NULL;
609 mock_device_info.reset();
610}
611
Paul Stewart81426132012-05-16 10:05:10 -0700612class ServiceWithMockSetEap : public ServiceUnderTest {
613 public:
614 ServiceWithMockSetEap(ControlInterface *control_interface,
615 EventDispatcher *dispatcher,
616 Metrics *metrics,
617 Manager *manager)
618 : ServiceUnderTest(control_interface, dispatcher, metrics, manager),
619 is_8021x_(false) {}
620 MOCK_METHOD1(set_eap, void(const EapCredentials &eap));
621 virtual bool Is8021x() const { return is_8021x_; }
622 void set_is_8021x(bool is_8021x) { is_8021x_ = is_8021x; }
623
624 private:
625 bool is_8021x_;
626};
627
628TEST_F(ServiceTest, SetEAPCredentialsOverRPC) {
629 scoped_refptr<ServiceWithMockSetEap> service(
630 new ServiceWithMockSetEap(control_interface(),
631 dispatcher(),
632 metrics(),
633 &mock_manager_));
634 string eap_credential_properties[] = {
635 flimflam::kEAPCertIDProperty,
636 flimflam::kEAPClientCertProperty,
637 flimflam::kEAPKeyIDProperty,
638 flimflam::kEAPPINProperty,
639 flimflam::kEapCaCertIDProperty,
640 flimflam::kEapIdentityProperty,
641 flimflam::kEapPasswordProperty,
642 flimflam::kEapPrivateKeyProperty
643 };
644 string eap_non_credential_properties[] = {
645 flimflam::kEAPEAPProperty,
646 flimflam::kEapPhase2AuthProperty,
647 flimflam::kEapAnonymousIdentityProperty,
648 flimflam::kEapPrivateKeyPasswordProperty,
649 flimflam::kEapKeyMgmtProperty,
650 flimflam::kEapCaCertNssProperty,
651 flimflam::kEapUseSystemCAsProperty
652 };
653 // While this is not an 802.1x-based service, none of these property
654 // changes should cause a call to set_eap().
655 EXPECT_CALL(*service, set_eap(_)).Times(0);
656 for (size_t i = 0; i < arraysize(eap_credential_properties); ++i)
657 service->OnPropertyChanged(eap_credential_properties[i]);
658 for (size_t i = 0; i < arraysize(eap_non_credential_properties); ++i)
659 service->OnPropertyChanged(eap_non_credential_properties[i]);
660
661 service->set_is_8021x(true);
662
663 // When this is an 802.1x-based service, set_eap should be called for
664 // all credential-carrying properties.
665 for (size_t i = 0; i < arraysize(eap_credential_properties); ++i) {
666 EXPECT_CALL(*service, set_eap(_)).Times(1);
667 service->OnPropertyChanged(eap_credential_properties[i]);
668 Mock::VerifyAndClearExpectations(service.get());
669 }
670 EXPECT_CALL(*service, set_eap(_)).Times(0);
671 for (size_t i = 0; i < arraysize(eap_non_credential_properties); ++i)
672 service->OnPropertyChanged(eap_non_credential_properties[i]);
673}
674
Paul Stewartbc6e7392012-05-24 07:07:48 -0700675TEST_F(ServiceTest, Certification) {
676 EXPECT_FALSE(service_->eap_.remote_certification.size());
677
678 ScopedMockLog log;
679 EXPECT_CALL(log, Log(logging::LOG_WARNING, _,
680 HasSubstr("exceeds our maximum"))).Times(2);
681 string kSubject("foo");
682 EXPECT_FALSE(service_->AddEAPCertification(
683 kSubject, Service::kEAPMaxCertificationElements));
684 EXPECT_FALSE(service_->AddEAPCertification(
685 kSubject, Service::kEAPMaxCertificationElements + 1));
686 EXPECT_FALSE(service_->eap_.remote_certification.size());
687 Mock::VerifyAndClearExpectations(&log);
688
689 EXPECT_CALL(log,
690 Log(logging::LOG_INFO, _, HasSubstr("Received certification")))
691 .Times(1);
692 EXPECT_TRUE(service_->AddEAPCertification(
693 kSubject, Service::kEAPMaxCertificationElements - 1));
694 Mock::VerifyAndClearExpectations(&log);
695 EXPECT_EQ(Service::kEAPMaxCertificationElements,
696 service_->eap_.remote_certification.size());
697 for (size_t i = 0; i < Service::kEAPMaxCertificationElements - 1; ++i) {
698 EXPECT_TRUE(service_->eap_.remote_certification[i].empty());
699 }
700 EXPECT_EQ(kSubject, service_->eap_.remote_certification[
701 Service::kEAPMaxCertificationElements - 1]);
702
703 // Re-adding the same name in the same position should not generate a log.
704 EXPECT_CALL(log, Log(_, _, _)).Times(0);
705 EXPECT_TRUE(service_->AddEAPCertification(
706 kSubject, Service::kEAPMaxCertificationElements - 1));
707
708 // Replacing the item should generate a log message.
709 EXPECT_CALL(log,
710 Log(logging::LOG_INFO, _, HasSubstr("Received certification")))
711 .Times(1);
712 EXPECT_TRUE(service_->AddEAPCertification(
713 kSubject + "x", Service::kEAPMaxCertificationElements - 1));
714}
715
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700716} // namespace shill