blob: 7e0f8aa80e9c699677779d1338a17c568f23a88b [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
Darin Petkov58f0b6d2012-06-12 12:52:30 +020084TEST_F(ServiceTest, CalculateState) {
85 service_->state_ = Service::kStateConnected;
86 Error error;
87 EXPECT_EQ(flimflam::kStateReady, service_->CalculateState(&error));
88 EXPECT_TRUE(error.IsSuccess());
89}
90
91TEST_F(ServiceTest, CalculateTechnology) {
92 service_->technology_ = Technology::kWifi;
93 Error error;
94 EXPECT_EQ(flimflam::kTypeWifi, service_->CalculateTechnology(&error));
95 EXPECT_TRUE(error.IsSuccess());
96}
97
Chris Masonea8a2c252011-06-27 22:16:30 -070098TEST_F(ServiceTest, GetProperties) {
99 map<string, ::DBus::Variant> props;
100 Error error(Error::kInvalidProperty, "");
101 {
102 ::DBus::Error dbus_error;
Paul Stewartd215af62012-04-24 23:25:50 -0700103 string expected("true");
mukesh agrawalde29fa82011-09-16 16:16:36 -0700104 service_->mutable_store()->SetStringProperty(flimflam::kCheckPortalProperty,
105 expected,
106 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700107 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700108 ASSERT_FALSE(props.find(flimflam::kCheckPortalProperty) == props.end());
109 EXPECT_EQ(props[flimflam::kCheckPortalProperty].reader().get_string(),
110 expected);
111 }
112 {
113 ::DBus::Error dbus_error;
114 bool expected = true;
Thieu Le284fe792012-01-31 17:53:19 -0800115 service_->set_favorite(true);
mukesh agrawalde29fa82011-09-16 16:16:36 -0700116 service_->mutable_store()->SetBoolProperty(flimflam::kAutoConnectProperty,
117 expected,
118 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700119 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700120 ASSERT_FALSE(props.find(flimflam::kAutoConnectProperty) == props.end());
121 EXPECT_EQ(props[flimflam::kAutoConnectProperty].reader().get_bool(),
122 expected);
123 }
124 {
125 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -0700126 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700127 ASSERT_FALSE(props.find(flimflam::kConnectableProperty) == props.end());
128 EXPECT_EQ(props[flimflam::kConnectableProperty].reader().get_bool(), false);
129 }
130 {
131 ::DBus::Error dbus_error;
132 int32 expected = 127;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700133 service_->mutable_store()->SetInt32Property(flimflam::kPriorityProperty,
134 expected,
135 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700136 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700137 ASSERT_FALSE(props.find(flimflam::kPriorityProperty) == props.end());
138 EXPECT_EQ(props[flimflam::kPriorityProperty].reader().get_int32(),
139 expected);
140 }
Chris Masone95207da2011-06-29 16:50:49 -0700141 {
142 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -0700143 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masone95207da2011-06-29 16:50:49 -0700144 ASSERT_FALSE(props.find(flimflam::kDeviceProperty) == props.end());
Jason Glasgowacdc11f2012-03-30 14:12:22 -0400145 EXPECT_EQ(props[flimflam::kDeviceProperty].reader().get_path(),
Paul Stewart03dba0b2011-08-22 16:32:45 -0700146 string(ServiceUnderTest::kRpcId));
Chris Masone95207da2011-06-29 16:50:49 -0700147 }
Chris Masonea8a2c252011-06-27 22:16:30 -0700148}
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700149
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800150TEST_F(ServiceTest, SetProperty) {
Chris Masonea8a2c252011-06-27 22:16:30 -0700151 {
152 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800153 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
154 flimflam::kSaveCredentialsProperty,
155 PropertyStoreTest::kBoolV,
156 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700157 }
158 {
159 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800160 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
161 flimflam::kPriorityProperty,
162 PropertyStoreTest::kInt32V,
163 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700164 }
165 {
166 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800167 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
168 flimflam::kEAPEAPProperty,
169 PropertyStoreTest::kStringV,
170 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700171 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700172 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
Chris Masonea8a2c252011-06-27 22:16:30 -0700173 {
174 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800175 EXPECT_FALSE(DBusAdaptor::SetProperty(service_->mutable_store(),
176 flimflam::kFavoriteProperty,
177 PropertyStoreTest::kBoolV,
178 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700179 EXPECT_EQ(invalid_args(), error.name());
Chris Masonea8a2c252011-06-27 22:16:30 -0700180 }
Thieu Le284fe792012-01-31 17:53:19 -0800181 {
182 ::DBus::Error error;
183 service_->set_favorite(true);
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800184 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
185 flimflam::kAutoConnectProperty,
186 PropertyStoreTest::kBoolV,
187 &error));
Thieu Le284fe792012-01-31 17:53:19 -0800188 }
189 {
190 ::DBus::Error error;
191 service_->set_favorite(false);
Wade Guthrie4f28e8b2012-04-11 10:52:07 -0700192 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800193 flimflam::kAutoConnectProperty,
194 PropertyStoreTest::kBoolV,
195 &error));
Thieu Le284fe792012-01-31 17:53:19 -0800196 }
Paul Stewart0c438332012-04-11 07:55:27 -0700197 // Ensure that we can perform a trivial set of the Name property (to its
198 // current value) but an attempt to set the property to a different value
199 // fails.
200 {
201 ::DBus::Error error;
202 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
203 flimflam::kNameProperty,
204 DBusAdaptor::StringToVariant(
205 service_->friendly_name()),
206 &error));
207 }
208 {
209 ::DBus::Error error;
210 EXPECT_FALSE(DBusAdaptor::SetProperty(service_->mutable_store(),
211 flimflam::kNameProperty,
212 PropertyStoreTest::kStringV,
213 &error));
214 EXPECT_EQ(invalid_args(), error.name());
215 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700216}
217
Darin Petkovba40dd32011-07-11 20:06:39 -0700218TEST_F(ServiceTest, Load) {
219 NiceMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700220 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
221 EXPECT_CALL(storage, GetString(storage_id_, _, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700222 .Times(AtLeast(1))
223 .WillRepeatedly(Return(true));
Chris Masone9d779932011-08-25 16:33:41 -0700224 EXPECT_TRUE(service_->Load(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700225}
226
227TEST_F(ServiceTest, LoadFail) {
228 StrictMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700229 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(false));
Chris Masone9d779932011-08-25 16:33:41 -0700230 EXPECT_FALSE(service_->Load(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700231}
232
233TEST_F(ServiceTest, SaveString) {
234 MockStore storage;
235 static const char kKey[] = "test-key";
236 static const char kData[] = "test-data";
Chris Masone34af2182011-08-22 11:59:36 -0700237 EXPECT_CALL(storage, SetString(storage_id_, kKey, kData))
Darin Petkovba40dd32011-07-11 20:06:39 -0700238 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700239 service_->SaveString(&storage, storage_id_, kKey, kData, false, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700240}
241
242TEST_F(ServiceTest, SaveStringCrypted) {
243 MockStore storage;
244 static const char kKey[] = "test-key";
245 static const char kData[] = "test-data";
Chris Masone34af2182011-08-22 11:59:36 -0700246 EXPECT_CALL(storage, SetCryptedString(storage_id_, kKey, kData))
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, kData, true, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700249}
250
251TEST_F(ServiceTest, SaveStringDontSave) {
252 MockStore storage;
253 static const char kKey[] = "test-key";
Chris Masone34af2182011-08-22 11:59:36 -0700254 EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
Darin Petkovba40dd32011-07-11 20:06:39 -0700255 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700256 service_->SaveString(&storage, storage_id_, kKey, "data", false, false);
Darin Petkovba40dd32011-07-11 20:06:39 -0700257}
258
259TEST_F(ServiceTest, SaveStringEmpty) {
260 MockStore storage;
261 static const char kKey[] = "test-key";
Chris Masone34af2182011-08-22 11:59:36 -0700262 EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
Darin Petkovba40dd32011-07-11 20:06:39 -0700263 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700264 service_->SaveString(&storage, storage_id_, kKey, "", true, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700265}
266
267TEST_F(ServiceTest, Save) {
268 NiceMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700269 EXPECT_CALL(storage, SetString(storage_id_, _, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700270 .Times(AtLeast(1))
271 .WillRepeatedly(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700272 EXPECT_CALL(storage, DeleteKey(storage_id_, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700273 .Times(AtLeast(1))
274 .WillRepeatedly(Return(true));
Chris Masone9d779932011-08-25 16:33:41 -0700275 EXPECT_TRUE(service_->Save(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700276}
277
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800278TEST_F(ServiceTest, Unload) {
279 NiceMock<MockStore> storage;
280 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
281 static const string string_value("value");
282 EXPECT_CALL(storage, GetString(storage_id_, _, _))
283 .Times(AtLeast(1))
284 .WillRepeatedly(DoAll(SetArgumentPointee<2>(string_value), Return(true)));
285 ASSERT_TRUE(service_->Load(&storage));
Paul Stewarte7cce8f2012-09-11 10:56:38 -0700286 // TODO(pstew): Only two string properties in the service are tested as
mukesh agrawalcf24a242012-05-21 16:46:11 -0700287 // a sentinel that properties are being set and reset at the right times.
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800288 // However, since property load/store is essentially a manual process,
289 // it is error prone and should either be exhaustively unit-tested or
290 // a generic framework for registering loaded/stored properties should
291 // be created. crosbug.com/24859
292 EXPECT_EQ(string_value, service_->ui_data_);
Paul Stewarte7cce8f2012-09-11 10:56:38 -0700293 EXPECT_EQ(string_value, service_->guid_);
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800294 service_->Unload();
295 EXPECT_EQ(string(""), service_->ui_data_);
Paul Stewarte7cce8f2012-09-11 10:56:38 -0700296 EXPECT_EQ(string(""), service_->guid_);
Philipp Neubeckf883a7b2012-09-14 19:52:44 +0200297 EXPECT_FALSE(service_->explicitly_disconnected_);
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800298}
299
Paul Stewart03dba0b2011-08-22 16:32:45 -0700300TEST_F(ServiceTest, State) {
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400301 EXPECT_EQ(Service::kStateIdle, service_->state());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700302 EXPECT_EQ(Service::kFailureUnknown, service_->failure());
Paul Stewartf2d60912012-07-15 08:37:30 -0700303 const string unknown_error(
304 Service::ConnectFailureToString(Service::kFailureUnknown));
305 EXPECT_EQ(unknown_error, service_->error());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700306
mukesh agrawal00917ce2011-11-22 23:56:55 +0000307 ServiceRefPtr service_ref(service_);
mukesh agrawalf2f68a52011-09-01 12:15:48 -0700308
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400309 EXPECT_CALL(*dynamic_cast<ServiceMockAdaptor *>(service_->adaptor_.get()),
mukesh agrawalcf24a242012-05-21 16:46:11 -0700310 EmitStringChanged(flimflam::kStateProperty, _)).Times(7);
Paul Stewartf2d60912012-07-15 08:37:30 -0700311 EXPECT_CALL(*dynamic_cast<ServiceMockAdaptor *>(service_->adaptor_.get()),
312 EmitStringChanged(flimflam::kErrorProperty, _)).Times(4);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700313 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
314 service_->SetState(Service::kStateConnected);
315 // A second state change shouldn't cause another update
316 service_->SetState(Service::kStateConnected);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700317 EXPECT_EQ(Service::kStateConnected, service_->state());
318 EXPECT_EQ(Service::kFailureUnknown, service_->failure());
mukesh agrawalcf24a242012-05-21 16:46:11 -0700319 EXPECT_TRUE(service_->has_ever_connected_);
mukesh agrawal568b5c62012-02-28 14:44:47 -0800320
Paul Stewart03dba0b2011-08-22 16:32:45 -0700321 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
322 service_->SetState(Service::kStateDisconnected);
323
324 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
325 service_->SetFailure(Service::kFailureOutOfRange);
mukesh agrawal568b5c62012-02-28 14:44:47 -0800326 EXPECT_TRUE(service_->IsFailed());
327 EXPECT_GT(service_->failed_time_, 0);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700328 EXPECT_EQ(Service::kStateFailure, service_->state());
329 EXPECT_EQ(Service::kFailureOutOfRange, service_->failure());
Paul Stewartf2d60912012-07-15 08:37:30 -0700330 const string out_of_range_error(
331 Service::ConnectFailureToString(Service::kFailureOutOfRange));
332 EXPECT_EQ(out_of_range_error, service_->error());
mukesh agrawal568b5c62012-02-28 14:44:47 -0800333
334 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
335 service_->SetState(Service::kStateConnected);
336 EXPECT_FALSE(service_->IsFailed());
337 EXPECT_EQ(service_->failed_time_, 0);
Paul Stewartf2d60912012-07-15 08:37:30 -0700338 EXPECT_EQ(unknown_error, service_->error());
mukesh agrawal568b5c62012-02-28 14:44:47 -0800339
340 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
341 service_->SetFailureSilent(Service::kFailurePinMissing);
342 EXPECT_TRUE(service_->IsFailed());
343 EXPECT_GT(service_->failed_time_, 0);
344 EXPECT_EQ(Service::kStateIdle, service_->state());
345 EXPECT_EQ(Service::kFailurePinMissing, service_->failure());
Paul Stewartf2d60912012-07-15 08:37:30 -0700346 const string pin_missing_error(
347 Service::ConnectFailureToString(Service::kFailurePinMissing));
348 EXPECT_EQ(pin_missing_error, service_->error());
mukesh agrawalcf24a242012-05-21 16:46:11 -0700349
350 // If the Service has a Profile, the profile should be saved when
351 // the service enters kStateConnected. (The case where the service
352 // doesn't have a profile is tested above.)
353 MockProfileRefPtr mock_profile(
354 new MockProfile(control_interface(), &mock_manager_));
355 NiceMock<MockStore> storage;
356 service_->set_profile(mock_profile);
357 service_->has_ever_connected_ = false;
358 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
359 EXPECT_CALL(*mock_profile, GetConstStorage())
360 .WillOnce(Return(&storage));
361 EXPECT_CALL(*mock_profile, UpdateService(service_ref));
362 service_->SetState(Service::kStateConnected);
363 EXPECT_TRUE(service_->has_ever_connected_);
364 service_->set_profile(NULL); // Break reference cycle.
365
366 // Similar to the above, but emulate an emphemeral profile, which
367 // has no storage. We can't update the service in the profile, but
368 // we should not crash.
369 service_->state_ = Service::kStateIdle; // Skips state change logic.
370 service_->set_profile(mock_profile);
371 service_->has_ever_connected_ = false;
372 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
373 EXPECT_CALL(*mock_profile, GetConstStorage()).
374 WillOnce(Return(static_cast<StoreInterface *>(NULL)));
375 service_->SetState(Service::kStateConnected);
376 EXPECT_TRUE(service_->has_ever_connected_);
377 service_->set_profile(NULL); // Break reference cycle.
Paul Stewart03dba0b2011-08-22 16:32:45 -0700378}
379
Darin Petkovb100ae72011-08-24 16:19:45 -0700380TEST_F(ServiceTest, ActivateCellularModem) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500381 ResultCallback callback =
382 Bind(&ServiceTest::TestCallback, Unretained(this));
383 EXPECT_CALL(*this, TestCallback(_)).Times(0);
Darin Petkovb100ae72011-08-24 16:19:45 -0700384 Error error;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500385 service_->ActivateCellularModem("Carrier", &error, callback);
386 EXPECT_TRUE(error.IsFailure());
Darin Petkovb100ae72011-08-24 16:19:45 -0700387}
388
mukesh agrawal00917ce2011-11-22 23:56:55 +0000389TEST_F(ServiceTest, MakeFavorite) {
390 EXPECT_FALSE(service_->favorite());
391 EXPECT_FALSE(service_->auto_connect());
392
393 service_->MakeFavorite();
394 EXPECT_TRUE(service_->favorite());
395 EXPECT_TRUE(service_->auto_connect());
396}
397
398TEST_F(ServiceTest, ReMakeFavorite) {
399 service_->MakeFavorite();
400 EXPECT_TRUE(service_->favorite());
401 EXPECT_TRUE(service_->auto_connect());
402
403 service_->set_auto_connect(false);
404 service_->MakeFavorite();
405 EXPECT_TRUE(service_->favorite());
406 EXPECT_FALSE(service_->auto_connect());
407}
408
mukesh agrawal76d13882012-01-12 15:23:11 -0800409TEST_F(ServiceTest, IsAutoConnectable) {
mukesh agrawalbf14e942012-03-02 14:36:34 -0800410 const char *reason;
mukesh agrawal76d13882012-01-12 15:23:11 -0800411 service_->set_connectable(true);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800412 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawal76d13882012-01-12 15:23:11 -0800413
mukesh agrawaladb68482012-01-17 16:31:51 -0800414 // We should not auto-connect to a Service that a user has
415 // deliberately disconnected.
416 Error error;
417 service_->Disconnect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800418 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
419 EXPECT_STREQ(Service::kAutoConnExplicitDisconnect, reason);
mukesh agrawaladb68482012-01-17 16:31:51 -0800420
421 // But if the Service is reloaded, it is eligible for auto-connect
422 // again.
423 NiceMock<MockStore> storage;
424 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
425 EXPECT_TRUE(service_->Load(&storage));
mukesh agrawalbf14e942012-03-02 14:36:34 -0800426 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800427
428 // A deliberate Connect should also re-enable auto-connect.
429 service_->Disconnect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800430 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800431 service_->Connect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800432 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800433
434 // TODO(quiche): After we have resume handling in place, test that
435 // we re-enable auto-connect on resume. crosbug.com/25213
436
mukesh agrawal76d13882012-01-12 15:23:11 -0800437 service_->SetState(Service::kStateConnected);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800438 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
439 EXPECT_STREQ(Service::kAutoConnConnected, reason);
mukesh agrawal76d13882012-01-12 15:23:11 -0800440
441 service_->SetState(Service::kStateAssociating);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800442 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
443 EXPECT_STREQ(Service::kAutoConnConnecting, reason);
mukesh agrawal76d13882012-01-12 15:23:11 -0800444}
445
Paul Stewartcb59fed2012-03-21 21:14:46 -0700446TEST_F(ServiceTest, ConfigureBadProperty) {
447 KeyValueStore args;
448 args.SetString("XXXInvalid", "Value");
449 Error error;
450 service_->Configure(args, &error);
451 EXPECT_FALSE(error.IsSuccess());
452}
453
454TEST_F(ServiceTest, ConfigureBoolProperty) {
455 service_->MakeFavorite();
456 service_->set_auto_connect(false);
457 ASSERT_FALSE(service_->auto_connect());
458 KeyValueStore args;
459 args.SetBool(flimflam::kAutoConnectProperty, true);
460 Error error;
461 service_->Configure(args, &error);
462 EXPECT_TRUE(error.IsSuccess());
463 EXPECT_TRUE(service_->auto_connect());
464}
465
466TEST_F(ServiceTest, ConfigureStringProperty) {
467 const string kEAPManagement0 = "management_zero";
468 const string kEAPManagement1 = "management_one";
469 service_->SetEAPKeyManagement(kEAPManagement0);
470 ASSERT_EQ(kEAPManagement0, service_->GetEAPKeyManagement());
471 KeyValueStore args;
472 args.SetString(flimflam::kEapKeyMgmtProperty, kEAPManagement1);
473 Error error;
474 service_->Configure(args, &error);
475 EXPECT_TRUE(error.IsSuccess());
476 EXPECT_EQ(kEAPManagement1, service_->GetEAPKeyManagement());
477}
478
479TEST_F(ServiceTest, ConfigureIgnoredProperty) {
480 service_->MakeFavorite();
481 service_->set_auto_connect(false);
482 ASSERT_FALSE(service_->auto_connect());
483 KeyValueStore args;
484 args.SetBool(flimflam::kAutoConnectProperty, true);
485 Error error;
486 service_->IgnoreParameterForConfigure(flimflam::kAutoConnectProperty);
487 service_->Configure(args, &error);
488 EXPECT_TRUE(error.IsSuccess());
489 EXPECT_FALSE(service_->auto_connect());
490}
491
Paul Stewart10ccbb32012-04-26 15:59:30 -0700492TEST_F(ServiceTest, IsRemembered) {
493 ServiceConstRefPtr service_ref(service_);
494 service_->set_profile(NULL);
495 EXPECT_CALL(mock_manager_, IsServiceEphemeral(_)).Times(0);
496 EXPECT_FALSE(service_->IsRemembered());
497
498 scoped_refptr<MockProfile> profile(
499 new StrictMock<MockProfile>(control_interface(), manager()));
500 service_->set_profile(profile);
501 EXPECT_CALL(mock_manager_, IsServiceEphemeral(service_ref))
502 .WillOnce(Return(true))
503 .WillOnce(Return(false));
504 EXPECT_FALSE(service_->IsRemembered());
505 EXPECT_TRUE(service_->IsRemembered());
506}
507
Paul Stewartff14b022012-04-24 20:06:23 -0700508TEST_F(ServiceTest, OnPropertyChanged) {
509 scoped_refptr<MockProfile> profile(
510 new StrictMock<MockProfile>(control_interface(), manager()));
511 service_->set_profile(NULL);
512 // Expect no crash.
513 service_->OnPropertyChanged("");
514
515 // Expect no call to Update if the profile has no storage.
516 service_->set_profile(profile);
517 EXPECT_CALL(*profile, UpdateService(_)).Times(0);
518 EXPECT_CALL(*profile, GetConstStorage())
519 .WillOnce(Return(reinterpret_cast<StoreInterface *>(NULL)));
520 service_->OnPropertyChanged("");
521
522 // Expect call to Update if the profile has storage.
523 EXPECT_CALL(*profile, UpdateService(_)).Times(1);
524 NiceMock<MockStore> storage;
525 EXPECT_CALL(*profile, GetConstStorage()).WillOnce(Return(&storage));
526 service_->OnPropertyChanged("");
527}
528
Paul Stewartd215af62012-04-24 23:25:50 -0700529
530TEST_F(ServiceTest, RecheckPortal) {
531 ServiceRefPtr service_ref(service_);
532 service_->state_ = Service::kStateIdle;
533 EXPECT_CALL(mock_manager_, RecheckPortalOnService(_)).Times(0);
534 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
535
536 service_->state_ = Service::kStatePortal;
537 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
538 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
539
540 service_->state_ = Service::kStateConnected;
541 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
542 service_->OnPropertyChanged(flimflam::kProxyConfigProperty);
543
544 service_->state_ = Service::kStateOnline;
545 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
546 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
547
548 service_->state_ = Service::kStatePortal;
549 EXPECT_CALL(mock_manager_, RecheckPortalOnService(_)).Times(0);
550 service_->OnPropertyChanged(flimflam::kEAPKeyIDProperty);
551}
552
553TEST_F(ServiceTest, SetCheckPortal) {
554 ServiceRefPtr service_ref(service_);
555 {
556 Error error;
557 service_->SetCheckPortal("false", &error);
558 EXPECT_TRUE(error.IsSuccess());
559 EXPECT_EQ(Service::kCheckPortalFalse, service_->check_portal_);
560 }
561 {
562 Error error;
563 service_->SetCheckPortal("true", &error);
564 EXPECT_TRUE(error.IsSuccess());
565 EXPECT_EQ(Service::kCheckPortalTrue, service_->check_portal_);
566 }
567 {
568 Error error;
569 service_->SetCheckPortal("auto", &error);
570 EXPECT_TRUE(error.IsSuccess());
571 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
572 }
573 {
574 Error error;
575 service_->SetCheckPortal("xxx", &error);
576 EXPECT_FALSE(error.IsSuccess());
577 EXPECT_EQ(Error::kInvalidArguments, error.type());
578 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
579 }
580}
581
Darin Petkovb2ba39f2012-06-06 10:33:43 +0200582TEST_F(ServiceTest, SetConnectable) {
583 EXPECT_FALSE(service_->connectable());
584
585 ServiceMockAdaptor *adaptor =
586 dynamic_cast<ServiceMockAdaptor *>(service_->adaptor());
587
588 EXPECT_CALL(*adaptor, EmitBoolChanged(_, _)).Times(0);
589 EXPECT_CALL(mock_manager_, HasService(_)).Times(0);
590 service_->SetConnectable(false);
591 EXPECT_FALSE(service_->connectable());
592
593 EXPECT_CALL(*adaptor, EmitBoolChanged(flimflam::kConnectableProperty, true));
594 EXPECT_CALL(mock_manager_, HasService(_)).WillOnce(Return(false));
595 EXPECT_CALL(mock_manager_, UpdateService(_)).Times(0);
596 service_->SetConnectable(true);
597 EXPECT_TRUE(service_->connectable());
598
599 EXPECT_CALL(*adaptor, EmitBoolChanged(flimflam::kConnectableProperty, false));
600 EXPECT_CALL(mock_manager_, HasService(_)).WillOnce(Return(true));
601 EXPECT_CALL(mock_manager_, UpdateService(_));
602 service_->SetConnectable(false);
603 EXPECT_FALSE(service_->connectable());
604
605 EXPECT_CALL(*adaptor, EmitBoolChanged(flimflam::kConnectableProperty, true));
606 EXPECT_CALL(mock_manager_, HasService(_)).WillOnce(Return(true));
607 EXPECT_CALL(mock_manager_, UpdateService(_));
608 service_->SetConnectable(true);
609 EXPECT_TRUE(service_->connectable());
610}
611
Paul Stewart9f32d192012-01-30 20:37:50 -0800612// Make sure a property is registered as a write only property
613// by reading and comparing all string properties returned on the store.
614// Subtle: We need to convert the test argument back and forth between
615// string and ::DBus::Variant because this is the parameter type that
616// our supeclass (PropertyStoreTest) is declared with.
617class ReadOnlyServicePropertyTest : public ServiceTest {};
618TEST_P(ReadOnlyServicePropertyTest, PropertyWriteOnly) {
Paul Stewart9f32d192012-01-30 20:37:50 -0800619 string property(GetParam().reader().get_string());
Paul Stewart8e7e4592012-04-29 09:47:48 -0700620 PropertyStoreInspector inspector(&service_->store());
Darin Petkov4682aa82012-05-31 16:24:11 +0200621 EXPECT_FALSE(inspector.GetStringProperty(property, NULL));
Paul Stewart9f32d192012-01-30 20:37:50 -0800622}
623
624INSTANTIATE_TEST_CASE_P(
625 ReadOnlyServicePropertyTestInstance,
626 ReadOnlyServicePropertyTest,
627 Values(
628 DBusAdaptor::StringToVariant(flimflam::kEapPrivateKeyPasswordProperty),
629 DBusAdaptor::StringToVariant(flimflam::kEapPasswordProperty)));
630
Paul Stewart10241e32012-04-23 18:15:06 -0700631
632TEST_F(ServiceTest, GetIPConfigRpcIdentifier) {
633 {
634 Error error;
635 EXPECT_EQ("/", service_->GetIPConfigRpcIdentifier(&error));
636 EXPECT_EQ(Error::kNotFound, error.type());
637 }
638
639 scoped_ptr<MockDeviceInfo> mock_device_info(
640 new NiceMock<MockDeviceInfo>(control_interface(), dispatcher(), metrics(),
641 &mock_manager_));
642 scoped_refptr<MockConnection> mock_connection(
643 new NiceMock<MockConnection>(mock_device_info.get()));
644
645 service_->connection_ = mock_connection;
646
647 {
648 Error error;
649 const string empty_string;
650 EXPECT_CALL(*mock_connection, ipconfig_rpc_identifier())
651 .WillOnce(ReturnRef(empty_string));
652 EXPECT_EQ("/", service_->GetIPConfigRpcIdentifier(&error));
653 EXPECT_EQ(Error::kNotFound, error.type());
654 }
655
656 {
657 Error error;
658 const string nonempty_string("/ipconfig/path");
659 EXPECT_CALL(*mock_connection, ipconfig_rpc_identifier())
660 .WillOnce(ReturnRef(nonempty_string));
661 EXPECT_EQ(nonempty_string, service_->GetIPConfigRpcIdentifier(&error));
662 EXPECT_EQ(Error::kSuccess, error.type());
663 }
664
665 // Assure orderly destruction of the Connection before DeviceInfo.
666 service_->connection_ = NULL;
667 mock_connection = NULL;
668 mock_device_info.reset();
669}
670
Paul Stewart81426132012-05-16 10:05:10 -0700671class ServiceWithMockSetEap : public ServiceUnderTest {
672 public:
673 ServiceWithMockSetEap(ControlInterface *control_interface,
674 EventDispatcher *dispatcher,
675 Metrics *metrics,
676 Manager *manager)
677 : ServiceUnderTest(control_interface, dispatcher, metrics, manager),
678 is_8021x_(false) {}
679 MOCK_METHOD1(set_eap, void(const EapCredentials &eap));
680 virtual bool Is8021x() const { return is_8021x_; }
681 void set_is_8021x(bool is_8021x) { is_8021x_ = is_8021x; }
682
683 private:
684 bool is_8021x_;
685};
686
687TEST_F(ServiceTest, SetEAPCredentialsOverRPC) {
688 scoped_refptr<ServiceWithMockSetEap> service(
689 new ServiceWithMockSetEap(control_interface(),
690 dispatcher(),
691 metrics(),
692 &mock_manager_));
693 string eap_credential_properties[] = {
694 flimflam::kEAPCertIDProperty,
695 flimflam::kEAPClientCertProperty,
696 flimflam::kEAPKeyIDProperty,
697 flimflam::kEAPPINProperty,
698 flimflam::kEapCaCertIDProperty,
699 flimflam::kEapIdentityProperty,
700 flimflam::kEapPasswordProperty,
701 flimflam::kEapPrivateKeyProperty
702 };
703 string eap_non_credential_properties[] = {
704 flimflam::kEAPEAPProperty,
705 flimflam::kEapPhase2AuthProperty,
706 flimflam::kEapAnonymousIdentityProperty,
707 flimflam::kEapPrivateKeyPasswordProperty,
Paul Stewart81426132012-05-16 10:05:10 -0700708 flimflam::kEapCaCertNssProperty,
709 flimflam::kEapUseSystemCAsProperty
710 };
711 // While this is not an 802.1x-based service, none of these property
712 // changes should cause a call to set_eap().
713 EXPECT_CALL(*service, set_eap(_)).Times(0);
714 for (size_t i = 0; i < arraysize(eap_credential_properties); ++i)
715 service->OnPropertyChanged(eap_credential_properties[i]);
716 for (size_t i = 0; i < arraysize(eap_non_credential_properties); ++i)
717 service->OnPropertyChanged(eap_non_credential_properties[i]);
Paul Stewartadf79d82012-07-18 16:09:56 -0700718 service->OnPropertyChanged(flimflam::kEapKeyMgmtProperty);
Paul Stewart81426132012-05-16 10:05:10 -0700719
720 service->set_is_8021x(true);
721
722 // When this is an 802.1x-based service, set_eap should be called for
723 // all credential-carrying properties.
724 for (size_t i = 0; i < arraysize(eap_credential_properties); ++i) {
725 EXPECT_CALL(*service, set_eap(_)).Times(1);
726 service->OnPropertyChanged(eap_credential_properties[i]);
727 Mock::VerifyAndClearExpectations(service.get());
728 }
Paul Stewartadf79d82012-07-18 16:09:56 -0700729
730 // The key management property is a special case. While not strictly
731 // a credential, it can change which credentials are used. Therefore it
732 // should also trigger a call to set_eap();
733 EXPECT_CALL(*service, set_eap(_)).Times(1);
734 service->OnPropertyChanged(flimflam::kEapKeyMgmtProperty);
735 Mock::VerifyAndClearExpectations(service.get());
736
Paul Stewart81426132012-05-16 10:05:10 -0700737 EXPECT_CALL(*service, set_eap(_)).Times(0);
738 for (size_t i = 0; i < arraysize(eap_non_credential_properties); ++i)
739 service->OnPropertyChanged(eap_non_credential_properties[i]);
740}
741
Paul Stewartbc6e7392012-05-24 07:07:48 -0700742TEST_F(ServiceTest, Certification) {
743 EXPECT_FALSE(service_->eap_.remote_certification.size());
744
745 ScopedMockLog log;
746 EXPECT_CALL(log, Log(logging::LOG_WARNING, _,
747 HasSubstr("exceeds our maximum"))).Times(2);
748 string kSubject("foo");
749 EXPECT_FALSE(service_->AddEAPCertification(
750 kSubject, Service::kEAPMaxCertificationElements));
751 EXPECT_FALSE(service_->AddEAPCertification(
752 kSubject, Service::kEAPMaxCertificationElements + 1));
753 EXPECT_FALSE(service_->eap_.remote_certification.size());
754 Mock::VerifyAndClearExpectations(&log);
755
756 EXPECT_CALL(log,
757 Log(logging::LOG_INFO, _, HasSubstr("Received certification")))
758 .Times(1);
759 EXPECT_TRUE(service_->AddEAPCertification(
760 kSubject, Service::kEAPMaxCertificationElements - 1));
761 Mock::VerifyAndClearExpectations(&log);
762 EXPECT_EQ(Service::kEAPMaxCertificationElements,
763 service_->eap_.remote_certification.size());
764 for (size_t i = 0; i < Service::kEAPMaxCertificationElements - 1; ++i) {
765 EXPECT_TRUE(service_->eap_.remote_certification[i].empty());
766 }
767 EXPECT_EQ(kSubject, service_->eap_.remote_certification[
768 Service::kEAPMaxCertificationElements - 1]);
769
770 // Re-adding the same name in the same position should not generate a log.
771 EXPECT_CALL(log, Log(_, _, _)).Times(0);
772 EXPECT_TRUE(service_->AddEAPCertification(
773 kSubject, Service::kEAPMaxCertificationElements - 1));
774
775 // Replacing the item should generate a log message.
776 EXPECT_CALL(log,
777 Log(logging::LOG_INFO, _, HasSubstr("Received certification")))
778 .Times(1);
779 EXPECT_TRUE(service_->AddEAPCertification(
780 kSubject + "x", Service::kEAPMaxCertificationElements - 1));
781}
782
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700783} // namespace shill