blob: 76c7316fe93798f6e56f08c63bbfa62701310f1a [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"
Christopher Wiley0801d192012-09-24 11:57:15 -070025#include "shill/mock_event_dispatcher.h"
Paul Stewartbc6e7392012-05-24 07:07:48 -070026#include "shill/mock_log.h"
Paul Stewart03dba0b2011-08-22 16:32:45 -070027#include "shill/mock_manager.h"
Paul Stewartff14b022012-04-24 20:06:23 -070028#include "shill/mock_profile.h"
Darin Petkovba40dd32011-07-11 20:06:39 -070029#include "shill/mock_store.h"
Paul Stewart8e7e4592012-04-29 09:47:48 -070030#include "shill/property_store_inspector.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070031#include "shill/property_store_unittest.h"
Chris Masone6515aab2011-10-12 16:19:09 -070032#include "shill/service_under_test.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070033
Eric Shienbrood9a245532012-03-07 14:20:39 -050034using base::Bind;
35using base::Unretained;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070036using std::map;
37using std::string;
38using std::vector;
Darin Petkovba40dd32011-07-11 20:06:39 -070039using testing::_;
mukesh agrawalcf24a242012-05-21 16:46:11 -070040using testing::AnyNumber;
Darin Petkovba40dd32011-07-11 20:06:39 -070041using testing::AtLeast;
Paul Stewartd8ad3c42012-01-09 12:39:38 -080042using testing::DoAll;
Paul Stewartbc6e7392012-05-24 07:07:48 -070043using testing::HasSubstr;
Paul Stewart81426132012-05-16 10:05:10 -070044using testing::Mock;
Darin Petkovba40dd32011-07-11 20:06:39 -070045using testing::NiceMock;
46using testing::Return;
Paul Stewart10241e32012-04-23 18:15:06 -070047using testing::ReturnRef;
Darin Petkovba40dd32011-07-11 20:06:39 -070048using testing::StrictMock;
Paul Stewartd8ad3c42012-01-09 12:39:38 -080049using testing::SetArgumentPointee;
Darin Petkovba40dd32011-07-11 20:06:39 -070050using testing::Test;
Paul Stewart9f32d192012-01-30 20:37:50 -080051using testing::Values;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070052
53namespace shill {
54
55class ServiceTest : public PropertyStoreTest {
56 public:
Chris Masoneb925cc82011-06-22 15:39:57 -070057 ServiceTest()
Thieu Le3426c8f2012-01-11 17:35:11 -080058 : mock_manager_(control_interface(), dispatcher(), metrics(), glib()),
Chris Masone2176a882011-09-14 22:29:15 -070059 service_(new ServiceUnderTest(control_interface(),
60 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -080061 metrics(),
Paul Stewart03dba0b2011-08-22 16:32:45 -070062 &mock_manager_)),
Chris Masone9d779932011-08-25 16:33:41 -070063 storage_id_(ServiceUnderTest::kStorageId) {
64 }
Chris Masoneb925cc82011-06-22 15:39:57 -070065
Chris Masone3bd3c8c2011-06-13 08:20:26 -070066 virtual ~ServiceTest() {}
Chris Masoneb925cc82011-06-22 15:39:57 -070067
Eric Shienbrood9a245532012-03-07 14:20:39 -050068 MOCK_METHOD1(TestCallback, void(const Error &error));
69
Chris Masoneb925cc82011-06-22 15:39:57 -070070 protected:
mukesh agrawalcf24a242012-05-21 16:46:11 -070071 typedef scoped_refptr<MockProfile> MockProfileRefPtr;
Eric Shienbrood9a245532012-03-07 14:20:39 -050072
Paul Stewart03dba0b2011-08-22 16:32:45 -070073 MockManager mock_manager_;
74 scoped_refptr<ServiceUnderTest> service_;
Chris Masone34af2182011-08-22 11:59:36 -070075 string storage_id_;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070076};
77
Christopher Wiley0801d192012-09-24 11:57:15 -070078class AllMockServiceTest : public testing::Test {
79 public:
80 AllMockServiceTest()
81 : manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
82 service_(new ServiceUnderTest(&control_interface_,
83 &dispatcher_,
84 &metrics_,
85 &manager_)) { }
86 virtual ~AllMockServiceTest() {}
87
88 protected:
89 MockControl control_interface_;
90 StrictMock<MockEventDispatcher> dispatcher_;
91 MockGLib glib_;
92 NiceMock<MockMetrics> metrics_;
93 MockManager manager_;
94 scoped_refptr<ServiceUnderTest> service_;
95};
96
Darin Petkovba40dd32011-07-11 20:06:39 -070097TEST_F(ServiceTest, Constructor) {
98 EXPECT_TRUE(service_->save_credentials_);
99 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400100 EXPECT_EQ(Service::kStateIdle, service_->state());
mukesh agrawalcf24a242012-05-21 16:46:11 -0700101 EXPECT_FALSE(service_->has_ever_connected());
Darin Petkovba40dd32011-07-11 20:06:39 -0700102}
103
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200104TEST_F(ServiceTest, CalculateState) {
105 service_->state_ = Service::kStateConnected;
106 Error error;
107 EXPECT_EQ(flimflam::kStateReady, service_->CalculateState(&error));
108 EXPECT_TRUE(error.IsSuccess());
109}
110
111TEST_F(ServiceTest, CalculateTechnology) {
112 service_->technology_ = Technology::kWifi;
113 Error error;
114 EXPECT_EQ(flimflam::kTypeWifi, service_->CalculateTechnology(&error));
115 EXPECT_TRUE(error.IsSuccess());
116}
117
Chris Masonea8a2c252011-06-27 22:16:30 -0700118TEST_F(ServiceTest, GetProperties) {
119 map<string, ::DBus::Variant> props;
120 Error error(Error::kInvalidProperty, "");
121 {
122 ::DBus::Error dbus_error;
Paul Stewartd215af62012-04-24 23:25:50 -0700123 string expected("true");
mukesh agrawalde29fa82011-09-16 16:16:36 -0700124 service_->mutable_store()->SetStringProperty(flimflam::kCheckPortalProperty,
125 expected,
126 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700127 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700128 ASSERT_FALSE(props.find(flimflam::kCheckPortalProperty) == props.end());
129 EXPECT_EQ(props[flimflam::kCheckPortalProperty].reader().get_string(),
130 expected);
131 }
132 {
133 ::DBus::Error dbus_error;
134 bool expected = true;
Thieu Le284fe792012-01-31 17:53:19 -0800135 service_->set_favorite(true);
mukesh agrawalde29fa82011-09-16 16:16:36 -0700136 service_->mutable_store()->SetBoolProperty(flimflam::kAutoConnectProperty,
137 expected,
138 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700139 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700140 ASSERT_FALSE(props.find(flimflam::kAutoConnectProperty) == props.end());
141 EXPECT_EQ(props[flimflam::kAutoConnectProperty].reader().get_bool(),
142 expected);
143 }
144 {
145 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -0700146 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700147 ASSERT_FALSE(props.find(flimflam::kConnectableProperty) == props.end());
148 EXPECT_EQ(props[flimflam::kConnectableProperty].reader().get_bool(), false);
149 }
150 {
151 ::DBus::Error dbus_error;
152 int32 expected = 127;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700153 service_->mutable_store()->SetInt32Property(flimflam::kPriorityProperty,
154 expected,
155 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700156 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700157 ASSERT_FALSE(props.find(flimflam::kPriorityProperty) == props.end());
158 EXPECT_EQ(props[flimflam::kPriorityProperty].reader().get_int32(),
159 expected);
160 }
Chris Masone95207da2011-06-29 16:50:49 -0700161 {
162 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -0700163 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masone95207da2011-06-29 16:50:49 -0700164 ASSERT_FALSE(props.find(flimflam::kDeviceProperty) == props.end());
Jason Glasgowacdc11f2012-03-30 14:12:22 -0400165 EXPECT_EQ(props[flimflam::kDeviceProperty].reader().get_path(),
Paul Stewart03dba0b2011-08-22 16:32:45 -0700166 string(ServiceUnderTest::kRpcId));
Chris Masone95207da2011-06-29 16:50:49 -0700167 }
Chris Masonea8a2c252011-06-27 22:16:30 -0700168}
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700169
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800170TEST_F(ServiceTest, SetProperty) {
Chris Masonea8a2c252011-06-27 22:16:30 -0700171 {
172 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800173 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
174 flimflam::kSaveCredentialsProperty,
175 PropertyStoreTest::kBoolV,
176 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700177 }
178 {
179 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800180 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
181 flimflam::kPriorityProperty,
182 PropertyStoreTest::kInt32V,
183 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700184 }
185 {
186 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800187 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
188 flimflam::kEAPEAPProperty,
189 PropertyStoreTest::kStringV,
190 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700191 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700192 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
Chris Masonea8a2c252011-06-27 22:16:30 -0700193 {
194 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800195 EXPECT_FALSE(DBusAdaptor::SetProperty(service_->mutable_store(),
196 flimflam::kFavoriteProperty,
197 PropertyStoreTest::kBoolV,
198 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700199 EXPECT_EQ(invalid_args(), error.name());
Chris Masonea8a2c252011-06-27 22:16:30 -0700200 }
Thieu Le284fe792012-01-31 17:53:19 -0800201 {
202 ::DBus::Error error;
203 service_->set_favorite(true);
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800204 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
205 flimflam::kAutoConnectProperty,
206 PropertyStoreTest::kBoolV,
207 &error));
Thieu Le284fe792012-01-31 17:53:19 -0800208 }
209 {
210 ::DBus::Error error;
211 service_->set_favorite(false);
Wade Guthrie4f28e8b2012-04-11 10:52:07 -0700212 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800213 flimflam::kAutoConnectProperty,
214 PropertyStoreTest::kBoolV,
215 &error));
Thieu Le284fe792012-01-31 17:53:19 -0800216 }
Paul Stewart0c438332012-04-11 07:55:27 -0700217 // Ensure that we can perform a trivial set of the Name property (to its
218 // current value) but an attempt to set the property to a different value
219 // fails.
220 {
221 ::DBus::Error error;
222 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
223 flimflam::kNameProperty,
224 DBusAdaptor::StringToVariant(
225 service_->friendly_name()),
226 &error));
227 }
228 {
229 ::DBus::Error error;
230 EXPECT_FALSE(DBusAdaptor::SetProperty(service_->mutable_store(),
231 flimflam::kNameProperty,
232 PropertyStoreTest::kStringV,
233 &error));
234 EXPECT_EQ(invalid_args(), error.name());
235 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700236}
237
Darin Petkovba40dd32011-07-11 20:06:39 -0700238TEST_F(ServiceTest, Load) {
239 NiceMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700240 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
241 EXPECT_CALL(storage, GetString(storage_id_, _, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700242 .Times(AtLeast(1))
243 .WillRepeatedly(Return(true));
Chris Masone9d779932011-08-25 16:33:41 -0700244 EXPECT_TRUE(service_->Load(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700245}
246
247TEST_F(ServiceTest, LoadFail) {
248 StrictMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700249 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(false));
Chris Masone9d779932011-08-25 16:33:41 -0700250 EXPECT_FALSE(service_->Load(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700251}
252
253TEST_F(ServiceTest, SaveString) {
254 MockStore storage;
255 static const char kKey[] = "test-key";
256 static const char kData[] = "test-data";
Chris Masone34af2182011-08-22 11:59:36 -0700257 EXPECT_CALL(storage, SetString(storage_id_, kKey, kData))
Darin Petkovba40dd32011-07-11 20:06:39 -0700258 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700259 service_->SaveString(&storage, storage_id_, kKey, kData, false, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700260}
261
262TEST_F(ServiceTest, SaveStringCrypted) {
263 MockStore storage;
264 static const char kKey[] = "test-key";
265 static const char kData[] = "test-data";
Chris Masone34af2182011-08-22 11:59:36 -0700266 EXPECT_CALL(storage, SetCryptedString(storage_id_, kKey, kData))
Darin Petkovba40dd32011-07-11 20:06:39 -0700267 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700268 service_->SaveString(&storage, storage_id_, kKey, kData, true, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700269}
270
271TEST_F(ServiceTest, SaveStringDontSave) {
272 MockStore storage;
273 static const char kKey[] = "test-key";
Chris Masone34af2182011-08-22 11:59:36 -0700274 EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
Darin Petkovba40dd32011-07-11 20:06:39 -0700275 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700276 service_->SaveString(&storage, storage_id_, kKey, "data", false, false);
Darin Petkovba40dd32011-07-11 20:06:39 -0700277}
278
279TEST_F(ServiceTest, SaveStringEmpty) {
280 MockStore storage;
281 static const char kKey[] = "test-key";
Chris Masone34af2182011-08-22 11:59:36 -0700282 EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
Darin Petkovba40dd32011-07-11 20:06:39 -0700283 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700284 service_->SaveString(&storage, storage_id_, kKey, "", true, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700285}
286
287TEST_F(ServiceTest, Save) {
288 NiceMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700289 EXPECT_CALL(storage, SetString(storage_id_, _, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700290 .Times(AtLeast(1))
291 .WillRepeatedly(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700292 EXPECT_CALL(storage, DeleteKey(storage_id_, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700293 .Times(AtLeast(1))
294 .WillRepeatedly(Return(true));
Chris Masone9d779932011-08-25 16:33:41 -0700295 EXPECT_TRUE(service_->Save(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700296}
297
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800298TEST_F(ServiceTest, Unload) {
299 NiceMock<MockStore> storage;
300 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
301 static const string string_value("value");
302 EXPECT_CALL(storage, GetString(storage_id_, _, _))
303 .Times(AtLeast(1))
304 .WillRepeatedly(DoAll(SetArgumentPointee<2>(string_value), Return(true)));
Paul Stewart88769de2012-09-21 13:14:36 -0700305 EXPECT_CALL(storage, GetBool(storage_id_, _, _))
306 .Times(AtLeast(1))
307 .WillRepeatedly(DoAll(SetArgumentPointee<2>(true), Return(true)));
308 EXPECT_FALSE(service_->explicitly_disconnected_);
309 service_->explicitly_disconnected_ = true;
310 EXPECT_FALSE(service_->has_ever_connected_);
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800311 ASSERT_TRUE(service_->Load(&storage));
Paul Stewarte7cce8f2012-09-11 10:56:38 -0700312 // TODO(pstew): Only two string properties in the service are tested as
mukesh agrawalcf24a242012-05-21 16:46:11 -0700313 // a sentinel that properties are being set and reset at the right times.
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800314 // However, since property load/store is essentially a manual process,
315 // it is error prone and should either be exhaustively unit-tested or
316 // a generic framework for registering loaded/stored properties should
317 // be created. crosbug.com/24859
318 EXPECT_EQ(string_value, service_->ui_data_);
Paul Stewarte7cce8f2012-09-11 10:56:38 -0700319 EXPECT_EQ(string_value, service_->guid_);
Paul Stewart88769de2012-09-21 13:14:36 -0700320 EXPECT_FALSE(service_->explicitly_disconnected_);
321 EXPECT_TRUE(service_->has_ever_connected_);
322 service_->explicitly_disconnected_ = true;
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800323 service_->Unload();
324 EXPECT_EQ(string(""), service_->ui_data_);
Paul Stewarte7cce8f2012-09-11 10:56:38 -0700325 EXPECT_EQ(string(""), service_->guid_);
Philipp Neubeckf883a7b2012-09-14 19:52:44 +0200326 EXPECT_FALSE(service_->explicitly_disconnected_);
Paul Stewart88769de2012-09-21 13:14:36 -0700327 EXPECT_FALSE(service_->has_ever_connected_);
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800328}
329
Paul Stewart03dba0b2011-08-22 16:32:45 -0700330TEST_F(ServiceTest, State) {
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400331 EXPECT_EQ(Service::kStateIdle, service_->state());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700332 EXPECT_EQ(Service::kFailureUnknown, service_->failure());
Paul Stewartf2d60912012-07-15 08:37:30 -0700333 const string unknown_error(
334 Service::ConnectFailureToString(Service::kFailureUnknown));
335 EXPECT_EQ(unknown_error, service_->error());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700336
mukesh agrawal00917ce2011-11-22 23:56:55 +0000337 ServiceRefPtr service_ref(service_);
mukesh agrawalf2f68a52011-09-01 12:15:48 -0700338
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400339 EXPECT_CALL(*dynamic_cast<ServiceMockAdaptor *>(service_->adaptor_.get()),
mukesh agrawalcf24a242012-05-21 16:46:11 -0700340 EmitStringChanged(flimflam::kStateProperty, _)).Times(7);
Paul Stewartf2d60912012-07-15 08:37:30 -0700341 EXPECT_CALL(*dynamic_cast<ServiceMockAdaptor *>(service_->adaptor_.get()),
342 EmitStringChanged(flimflam::kErrorProperty, _)).Times(4);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700343 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
344 service_->SetState(Service::kStateConnected);
345 // A second state change shouldn't cause another update
346 service_->SetState(Service::kStateConnected);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700347 EXPECT_EQ(Service::kStateConnected, service_->state());
348 EXPECT_EQ(Service::kFailureUnknown, service_->failure());
mukesh agrawalcf24a242012-05-21 16:46:11 -0700349 EXPECT_TRUE(service_->has_ever_connected_);
mukesh agrawal568b5c62012-02-28 14:44:47 -0800350
Paul Stewart03dba0b2011-08-22 16:32:45 -0700351 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
352 service_->SetState(Service::kStateDisconnected);
353
354 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
355 service_->SetFailure(Service::kFailureOutOfRange);
mukesh agrawal568b5c62012-02-28 14:44:47 -0800356 EXPECT_TRUE(service_->IsFailed());
357 EXPECT_GT(service_->failed_time_, 0);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700358 EXPECT_EQ(Service::kStateFailure, service_->state());
359 EXPECT_EQ(Service::kFailureOutOfRange, service_->failure());
Paul Stewartf2d60912012-07-15 08:37:30 -0700360 const string out_of_range_error(
361 Service::ConnectFailureToString(Service::kFailureOutOfRange));
362 EXPECT_EQ(out_of_range_error, service_->error());
mukesh agrawal568b5c62012-02-28 14:44:47 -0800363
364 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
365 service_->SetState(Service::kStateConnected);
366 EXPECT_FALSE(service_->IsFailed());
367 EXPECT_EQ(service_->failed_time_, 0);
Paul Stewartf2d60912012-07-15 08:37:30 -0700368 EXPECT_EQ(unknown_error, service_->error());
mukesh agrawal568b5c62012-02-28 14:44:47 -0800369
370 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
371 service_->SetFailureSilent(Service::kFailurePinMissing);
372 EXPECT_TRUE(service_->IsFailed());
373 EXPECT_GT(service_->failed_time_, 0);
374 EXPECT_EQ(Service::kStateIdle, service_->state());
375 EXPECT_EQ(Service::kFailurePinMissing, service_->failure());
Paul Stewartf2d60912012-07-15 08:37:30 -0700376 const string pin_missing_error(
377 Service::ConnectFailureToString(Service::kFailurePinMissing));
378 EXPECT_EQ(pin_missing_error, service_->error());
mukesh agrawalcf24a242012-05-21 16:46:11 -0700379
380 // If the Service has a Profile, the profile should be saved when
381 // the service enters kStateConnected. (The case where the service
382 // doesn't have a profile is tested above.)
383 MockProfileRefPtr mock_profile(
384 new MockProfile(control_interface(), &mock_manager_));
385 NiceMock<MockStore> storage;
386 service_->set_profile(mock_profile);
387 service_->has_ever_connected_ = false;
388 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
389 EXPECT_CALL(*mock_profile, GetConstStorage())
390 .WillOnce(Return(&storage));
391 EXPECT_CALL(*mock_profile, UpdateService(service_ref));
392 service_->SetState(Service::kStateConnected);
393 EXPECT_TRUE(service_->has_ever_connected_);
394 service_->set_profile(NULL); // Break reference cycle.
395
396 // Similar to the above, but emulate an emphemeral profile, which
397 // has no storage. We can't update the service in the profile, but
398 // we should not crash.
399 service_->state_ = Service::kStateIdle; // Skips state change logic.
400 service_->set_profile(mock_profile);
401 service_->has_ever_connected_ = false;
402 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
403 EXPECT_CALL(*mock_profile, GetConstStorage()).
404 WillOnce(Return(static_cast<StoreInterface *>(NULL)));
405 service_->SetState(Service::kStateConnected);
406 EXPECT_TRUE(service_->has_ever_connected_);
407 service_->set_profile(NULL); // Break reference cycle.
Paul Stewart03dba0b2011-08-22 16:32:45 -0700408}
409
Darin Petkovb100ae72011-08-24 16:19:45 -0700410TEST_F(ServiceTest, ActivateCellularModem) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500411 ResultCallback callback =
412 Bind(&ServiceTest::TestCallback, Unretained(this));
413 EXPECT_CALL(*this, TestCallback(_)).Times(0);
Darin Petkovb100ae72011-08-24 16:19:45 -0700414 Error error;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500415 service_->ActivateCellularModem("Carrier", &error, callback);
416 EXPECT_TRUE(error.IsFailure());
Darin Petkovb100ae72011-08-24 16:19:45 -0700417}
418
mukesh agrawal00917ce2011-11-22 23:56:55 +0000419TEST_F(ServiceTest, MakeFavorite) {
420 EXPECT_FALSE(service_->favorite());
421 EXPECT_FALSE(service_->auto_connect());
422
423 service_->MakeFavorite();
424 EXPECT_TRUE(service_->favorite());
425 EXPECT_TRUE(service_->auto_connect());
426}
427
428TEST_F(ServiceTest, ReMakeFavorite) {
429 service_->MakeFavorite();
430 EXPECT_TRUE(service_->favorite());
431 EXPECT_TRUE(service_->auto_connect());
432
433 service_->set_auto_connect(false);
434 service_->MakeFavorite();
435 EXPECT_TRUE(service_->favorite());
436 EXPECT_FALSE(service_->auto_connect());
437}
438
mukesh agrawal76d13882012-01-12 15:23:11 -0800439TEST_F(ServiceTest, IsAutoConnectable) {
mukesh agrawalbf14e942012-03-02 14:36:34 -0800440 const char *reason;
mukesh agrawal76d13882012-01-12 15:23:11 -0800441 service_->set_connectable(true);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800442 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawal76d13882012-01-12 15:23:11 -0800443
mukesh agrawaladb68482012-01-17 16:31:51 -0800444 // We should not auto-connect to a Service that a user has
445 // deliberately disconnected.
446 Error error;
Christopher Wileyabd3b502012-09-26 13:08:52 -0700447 service_->UserInitiatedDisconnect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800448 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
449 EXPECT_STREQ(Service::kAutoConnExplicitDisconnect, reason);
mukesh agrawaladb68482012-01-17 16:31:51 -0800450
451 // But if the Service is reloaded, it is eligible for auto-connect
452 // again.
453 NiceMock<MockStore> storage;
454 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
455 EXPECT_TRUE(service_->Load(&storage));
mukesh agrawalbf14e942012-03-02 14:36:34 -0800456 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800457
458 // A deliberate Connect should also re-enable auto-connect.
Christopher Wileyabd3b502012-09-26 13:08:52 -0700459 service_->UserInitiatedDisconnect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800460 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800461 service_->Connect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800462 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800463
Christopher Wileyabd3b502012-09-26 13:08:52 -0700464 // A non-user initiated Disconnect doesn't change anything.
465 service_->Disconnect(&error);
466 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
467
Christopher Wileya4c61ae2012-10-01 11:04:30 -0700468 // A resume also re-enables auto-connect.
469 service_->UserInitiatedDisconnect(&error);
470 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
471 service_->OnAfterResume();
472 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800473
mukesh agrawal76d13882012-01-12 15:23:11 -0800474 service_->SetState(Service::kStateConnected);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800475 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
476 EXPECT_STREQ(Service::kAutoConnConnected, reason);
mukesh agrawal76d13882012-01-12 15:23:11 -0800477
478 service_->SetState(Service::kStateAssociating);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800479 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
480 EXPECT_STREQ(Service::kAutoConnConnecting, reason);
mukesh agrawal76d13882012-01-12 15:23:11 -0800481}
482
mukesh agrawal03c15ce2012-11-29 17:36:21 -0800483TEST_F(ServiceTest, AutoConnectLogging) {
484 ScopedMockLog log;
485 EXPECT_CALL(log, Log(_, _, _));
486 service_->set_connectable(true);
487
488 ScopeLogger::GetInstance()->EnableScopesByName("+service");
489 ScopeLogger::GetInstance()->set_verbose_level(1);
490 service_->SetState(Service::kStateConnected);
491 EXPECT_CALL(log, Log(-1, _, HasSubstr(Service::kAutoConnConnected)));
492 service_->AutoConnect();
493
494 ScopeLogger::GetInstance()->EnableScopesByName("-service");
495 ScopeLogger::GetInstance()->set_verbose_level(0);
496 EXPECT_CALL(log, Log(logging::LOG_INFO, _,
497 HasSubstr(Service::kAutoConnNotConnectable)));
498 service_->set_connectable(false);
499 service_->AutoConnect();
500}
501
502
Christopher Wiley0801d192012-09-24 11:57:15 -0700503TEST_F(AllMockServiceTest, AutoConnectWithFailures) {
504 const char *reason;
505 service_->set_connectable(true);
506 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
507
508 // The very first AutoConnect() doesn't trigger any throttling.
509 EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(0);
510 service_->AutoConnect();
511 Mock::VerifyAndClearExpectations(&dispatcher_);
512 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
513
514 // The second call does trigger some throttling.
515 EXPECT_CALL(dispatcher_, PostDelayedTask(_,
516 Service::kMinAutoConnectCooldownTimeMilliseconds));
517 service_->AutoConnect();
518 Mock::VerifyAndClearExpectations(&dispatcher_);
519 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
520 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
521
522 // Calling AutoConnect() again before the cooldown terminates does not change
523 // the timeout.
524 EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(0);
525 service_->AutoConnect();
526 Mock::VerifyAndClearExpectations(&dispatcher_);
527 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
528 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
529
530 // Once the timeout expires, we can AutoConnect() again.
531 service_->ReEnableAutoConnectTask();
532 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
533
534 // Timeouts increase exponentially.
535 uint64 next_cooldown_time = service_->auto_connect_cooldown_milliseconds_;
536 EXPECT_EQ(next_cooldown_time,
537 Service::kAutoConnectCooldownBackoffFactor *
538 Service::kMinAutoConnectCooldownTimeMilliseconds);
539 while (next_cooldown_time <=
540 Service::kMaxAutoConnectCooldownTimeMilliseconds) {
541 EXPECT_CALL(dispatcher_, PostDelayedTask(_, next_cooldown_time));
542 service_->AutoConnect();
543 Mock::VerifyAndClearExpectations(&dispatcher_);
544 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
545 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
546 service_->ReEnableAutoConnectTask();
547 next_cooldown_time *= Service::kAutoConnectCooldownBackoffFactor;
548 }
549
550 // Once we hit our cap, future timeouts are the same.
551 for (int32 i = 0; i < 2; i++) {
552 EXPECT_CALL(dispatcher_, PostDelayedTask(_,
553 Service::kMaxAutoConnectCooldownTimeMilliseconds));
554 service_->AutoConnect();
555 Mock::VerifyAndClearExpectations(&dispatcher_);
556 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
557 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
558 service_->ReEnableAutoConnectTask();
559 }
560
561 // Connecting successfully resets our cooldown.
562 service_->SetState(Service::kStateConnected);
563 service_->SetState(Service::kStateIdle);
564 reason = "";
565 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
566 EXPECT_STREQ("", reason);
567 EXPECT_EQ(service_->auto_connect_cooldown_milliseconds_, 0);
568
569 // But future AutoConnects behave as before
570 EXPECT_CALL(dispatcher_, PostDelayedTask(_,
571 Service::kMinAutoConnectCooldownTimeMilliseconds)).Times(1);
572 service_->AutoConnect();
573 service_->AutoConnect();
574 Mock::VerifyAndClearExpectations(&dispatcher_);
575 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
576 EXPECT_STREQ(Service::kAutoConnThrottled, reason);
577
578 // Cooldowns are forgotten if we go through a suspend/resume cycle.
579 service_->OnAfterResume();
580 reason = "";
581 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
582 EXPECT_STREQ("", reason);
583}
584
Paul Stewartcb59fed2012-03-21 21:14:46 -0700585TEST_F(ServiceTest, ConfigureBadProperty) {
586 KeyValueStore args;
587 args.SetString("XXXInvalid", "Value");
588 Error error;
589 service_->Configure(args, &error);
590 EXPECT_FALSE(error.IsSuccess());
591}
592
593TEST_F(ServiceTest, ConfigureBoolProperty) {
594 service_->MakeFavorite();
595 service_->set_auto_connect(false);
596 ASSERT_FALSE(service_->auto_connect());
597 KeyValueStore args;
598 args.SetBool(flimflam::kAutoConnectProperty, true);
599 Error error;
600 service_->Configure(args, &error);
601 EXPECT_TRUE(error.IsSuccess());
602 EXPECT_TRUE(service_->auto_connect());
603}
604
605TEST_F(ServiceTest, ConfigureStringProperty) {
606 const string kEAPManagement0 = "management_zero";
607 const string kEAPManagement1 = "management_one";
608 service_->SetEAPKeyManagement(kEAPManagement0);
609 ASSERT_EQ(kEAPManagement0, service_->GetEAPKeyManagement());
610 KeyValueStore args;
611 args.SetString(flimflam::kEapKeyMgmtProperty, kEAPManagement1);
612 Error error;
613 service_->Configure(args, &error);
614 EXPECT_TRUE(error.IsSuccess());
615 EXPECT_EQ(kEAPManagement1, service_->GetEAPKeyManagement());
616}
617
618TEST_F(ServiceTest, ConfigureIgnoredProperty) {
619 service_->MakeFavorite();
620 service_->set_auto_connect(false);
621 ASSERT_FALSE(service_->auto_connect());
622 KeyValueStore args;
623 args.SetBool(flimflam::kAutoConnectProperty, true);
624 Error error;
625 service_->IgnoreParameterForConfigure(flimflam::kAutoConnectProperty);
626 service_->Configure(args, &error);
627 EXPECT_TRUE(error.IsSuccess());
628 EXPECT_FALSE(service_->auto_connect());
629}
630
Paul Stewart10ccbb32012-04-26 15:59:30 -0700631TEST_F(ServiceTest, IsRemembered) {
632 ServiceConstRefPtr service_ref(service_);
633 service_->set_profile(NULL);
634 EXPECT_CALL(mock_manager_, IsServiceEphemeral(_)).Times(0);
635 EXPECT_FALSE(service_->IsRemembered());
636
637 scoped_refptr<MockProfile> profile(
638 new StrictMock<MockProfile>(control_interface(), manager()));
639 service_->set_profile(profile);
640 EXPECT_CALL(mock_manager_, IsServiceEphemeral(service_ref))
641 .WillOnce(Return(true))
642 .WillOnce(Return(false));
643 EXPECT_FALSE(service_->IsRemembered());
644 EXPECT_TRUE(service_->IsRemembered());
645}
646
Paul Stewartdf3c0a82012-11-09 15:54:33 -0800647TEST_F(ServiceTest, IsDependentOn) {
648 EXPECT_FALSE(service_->IsDependentOn(NULL));
649
650 scoped_ptr<MockDeviceInfo> mock_device_info(
651 new NiceMock<MockDeviceInfo>(control_interface(), dispatcher(), metrics(),
652 &mock_manager_));
653 scoped_refptr<MockConnection> mock_connection0(
654 new NiceMock<MockConnection>(mock_device_info.get()));
655 scoped_refptr<MockConnection> mock_connection1(
656 new NiceMock<MockConnection>(mock_device_info.get()));
657
658 service_->connection_ = mock_connection0;
659 EXPECT_CALL(*mock_connection0.get(), GetLowerConnection())
660 .WillRepeatedly(Return(mock_connection1));
661 EXPECT_FALSE(service_->IsDependentOn(NULL));
662
663 scoped_refptr<ServiceUnderTest> service1 =
664 new ServiceUnderTest(control_interface(),
665 dispatcher(),
666 metrics(),
667 &mock_manager_);
668 EXPECT_FALSE(service_->IsDependentOn(service1));
669
670 service1->connection_ = mock_connection0;
671 EXPECT_FALSE(service_->IsDependentOn(service1));
672
673 service1->connection_ = mock_connection1;
674 EXPECT_TRUE(service_->IsDependentOn(service1));
675
676 service_->connection_ = NULL;
677 service1->connection_ = NULL;
678}
679
Paul Stewartff14b022012-04-24 20:06:23 -0700680TEST_F(ServiceTest, OnPropertyChanged) {
681 scoped_refptr<MockProfile> profile(
682 new StrictMock<MockProfile>(control_interface(), manager()));
683 service_->set_profile(NULL);
684 // Expect no crash.
685 service_->OnPropertyChanged("");
686
687 // Expect no call to Update if the profile has no storage.
688 service_->set_profile(profile);
689 EXPECT_CALL(*profile, UpdateService(_)).Times(0);
690 EXPECT_CALL(*profile, GetConstStorage())
691 .WillOnce(Return(reinterpret_cast<StoreInterface *>(NULL)));
692 service_->OnPropertyChanged("");
693
694 // Expect call to Update if the profile has storage.
695 EXPECT_CALL(*profile, UpdateService(_)).Times(1);
696 NiceMock<MockStore> storage;
697 EXPECT_CALL(*profile, GetConstStorage()).WillOnce(Return(&storage));
698 service_->OnPropertyChanged("");
699}
700
Paul Stewartd215af62012-04-24 23:25:50 -0700701
702TEST_F(ServiceTest, RecheckPortal) {
703 ServiceRefPtr service_ref(service_);
704 service_->state_ = Service::kStateIdle;
705 EXPECT_CALL(mock_manager_, RecheckPortalOnService(_)).Times(0);
706 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
707
708 service_->state_ = Service::kStatePortal;
709 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
710 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
711
712 service_->state_ = Service::kStateConnected;
713 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
714 service_->OnPropertyChanged(flimflam::kProxyConfigProperty);
715
716 service_->state_ = Service::kStateOnline;
717 EXPECT_CALL(mock_manager_, RecheckPortalOnService(service_ref)).Times(1);
718 service_->OnPropertyChanged(flimflam::kCheckPortalProperty);
719
720 service_->state_ = Service::kStatePortal;
721 EXPECT_CALL(mock_manager_, RecheckPortalOnService(_)).Times(0);
722 service_->OnPropertyChanged(flimflam::kEAPKeyIDProperty);
723}
724
725TEST_F(ServiceTest, SetCheckPortal) {
726 ServiceRefPtr service_ref(service_);
727 {
728 Error error;
729 service_->SetCheckPortal("false", &error);
730 EXPECT_TRUE(error.IsSuccess());
731 EXPECT_EQ(Service::kCheckPortalFalse, service_->check_portal_);
732 }
733 {
734 Error error;
735 service_->SetCheckPortal("true", &error);
736 EXPECT_TRUE(error.IsSuccess());
737 EXPECT_EQ(Service::kCheckPortalTrue, service_->check_portal_);
738 }
739 {
740 Error error;
741 service_->SetCheckPortal("auto", &error);
742 EXPECT_TRUE(error.IsSuccess());
743 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
744 }
745 {
746 Error error;
747 service_->SetCheckPortal("xxx", &error);
748 EXPECT_FALSE(error.IsSuccess());
749 EXPECT_EQ(Error::kInvalidArguments, error.type());
750 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
751 }
752}
753
Darin Petkovb2ba39f2012-06-06 10:33:43 +0200754TEST_F(ServiceTest, SetConnectable) {
755 EXPECT_FALSE(service_->connectable());
756
757 ServiceMockAdaptor *adaptor =
758 dynamic_cast<ServiceMockAdaptor *>(service_->adaptor());
759
760 EXPECT_CALL(*adaptor, EmitBoolChanged(_, _)).Times(0);
761 EXPECT_CALL(mock_manager_, HasService(_)).Times(0);
762 service_->SetConnectable(false);
763 EXPECT_FALSE(service_->connectable());
764
765 EXPECT_CALL(*adaptor, EmitBoolChanged(flimflam::kConnectableProperty, true));
766 EXPECT_CALL(mock_manager_, HasService(_)).WillOnce(Return(false));
767 EXPECT_CALL(mock_manager_, UpdateService(_)).Times(0);
768 service_->SetConnectable(true);
769 EXPECT_TRUE(service_->connectable());
770
771 EXPECT_CALL(*adaptor, EmitBoolChanged(flimflam::kConnectableProperty, false));
772 EXPECT_CALL(mock_manager_, HasService(_)).WillOnce(Return(true));
773 EXPECT_CALL(mock_manager_, UpdateService(_));
774 service_->SetConnectable(false);
775 EXPECT_FALSE(service_->connectable());
776
777 EXPECT_CALL(*adaptor, EmitBoolChanged(flimflam::kConnectableProperty, true));
778 EXPECT_CALL(mock_manager_, HasService(_)).WillOnce(Return(true));
779 EXPECT_CALL(mock_manager_, UpdateService(_));
780 service_->SetConnectable(true);
781 EXPECT_TRUE(service_->connectable());
782}
783
Paul Stewart9f32d192012-01-30 20:37:50 -0800784// Make sure a property is registered as a write only property
785// by reading and comparing all string properties returned on the store.
786// Subtle: We need to convert the test argument back and forth between
787// string and ::DBus::Variant because this is the parameter type that
788// our supeclass (PropertyStoreTest) is declared with.
789class ReadOnlyServicePropertyTest : public ServiceTest {};
790TEST_P(ReadOnlyServicePropertyTest, PropertyWriteOnly) {
Paul Stewart9f32d192012-01-30 20:37:50 -0800791 string property(GetParam().reader().get_string());
Paul Stewart8e7e4592012-04-29 09:47:48 -0700792 PropertyStoreInspector inspector(&service_->store());
Darin Petkov4682aa82012-05-31 16:24:11 +0200793 EXPECT_FALSE(inspector.GetStringProperty(property, NULL));
Paul Stewart9f32d192012-01-30 20:37:50 -0800794}
795
796INSTANTIATE_TEST_CASE_P(
797 ReadOnlyServicePropertyTestInstance,
798 ReadOnlyServicePropertyTest,
799 Values(
800 DBusAdaptor::StringToVariant(flimflam::kEapPrivateKeyPasswordProperty),
801 DBusAdaptor::StringToVariant(flimflam::kEapPasswordProperty)));
802
Paul Stewart10241e32012-04-23 18:15:06 -0700803
804TEST_F(ServiceTest, GetIPConfigRpcIdentifier) {
805 {
806 Error error;
807 EXPECT_EQ("/", service_->GetIPConfigRpcIdentifier(&error));
808 EXPECT_EQ(Error::kNotFound, error.type());
809 }
810
811 scoped_ptr<MockDeviceInfo> mock_device_info(
812 new NiceMock<MockDeviceInfo>(control_interface(), dispatcher(), metrics(),
813 &mock_manager_));
814 scoped_refptr<MockConnection> mock_connection(
815 new NiceMock<MockConnection>(mock_device_info.get()));
816
817 service_->connection_ = mock_connection;
818
819 {
820 Error error;
821 const string empty_string;
822 EXPECT_CALL(*mock_connection, ipconfig_rpc_identifier())
823 .WillOnce(ReturnRef(empty_string));
824 EXPECT_EQ("/", service_->GetIPConfigRpcIdentifier(&error));
825 EXPECT_EQ(Error::kNotFound, error.type());
826 }
827
828 {
829 Error error;
830 const string nonempty_string("/ipconfig/path");
831 EXPECT_CALL(*mock_connection, ipconfig_rpc_identifier())
832 .WillOnce(ReturnRef(nonempty_string));
833 EXPECT_EQ(nonempty_string, service_->GetIPConfigRpcIdentifier(&error));
834 EXPECT_EQ(Error::kSuccess, error.type());
835 }
836
837 // Assure orderly destruction of the Connection before DeviceInfo.
838 service_->connection_ = NULL;
839 mock_connection = NULL;
840 mock_device_info.reset();
841}
842
Paul Stewart81426132012-05-16 10:05:10 -0700843class ServiceWithMockSetEap : public ServiceUnderTest {
844 public:
845 ServiceWithMockSetEap(ControlInterface *control_interface,
846 EventDispatcher *dispatcher,
847 Metrics *metrics,
848 Manager *manager)
849 : ServiceUnderTest(control_interface, dispatcher, metrics, manager),
850 is_8021x_(false) {}
851 MOCK_METHOD1(set_eap, void(const EapCredentials &eap));
852 virtual bool Is8021x() const { return is_8021x_; }
853 void set_is_8021x(bool is_8021x) { is_8021x_ = is_8021x; }
854
855 private:
856 bool is_8021x_;
857};
858
859TEST_F(ServiceTest, SetEAPCredentialsOverRPC) {
860 scoped_refptr<ServiceWithMockSetEap> service(
861 new ServiceWithMockSetEap(control_interface(),
862 dispatcher(),
863 metrics(),
864 &mock_manager_));
865 string eap_credential_properties[] = {
866 flimflam::kEAPCertIDProperty,
867 flimflam::kEAPClientCertProperty,
868 flimflam::kEAPKeyIDProperty,
869 flimflam::kEAPPINProperty,
870 flimflam::kEapCaCertIDProperty,
871 flimflam::kEapIdentityProperty,
872 flimflam::kEapPasswordProperty,
873 flimflam::kEapPrivateKeyProperty
874 };
875 string eap_non_credential_properties[] = {
876 flimflam::kEAPEAPProperty,
877 flimflam::kEapPhase2AuthProperty,
878 flimflam::kEapAnonymousIdentityProperty,
879 flimflam::kEapPrivateKeyPasswordProperty,
Paul Stewart81426132012-05-16 10:05:10 -0700880 flimflam::kEapCaCertNssProperty,
881 flimflam::kEapUseSystemCAsProperty
882 };
883 // While this is not an 802.1x-based service, none of these property
884 // changes should cause a call to set_eap().
885 EXPECT_CALL(*service, set_eap(_)).Times(0);
886 for (size_t i = 0; i < arraysize(eap_credential_properties); ++i)
887 service->OnPropertyChanged(eap_credential_properties[i]);
888 for (size_t i = 0; i < arraysize(eap_non_credential_properties); ++i)
889 service->OnPropertyChanged(eap_non_credential_properties[i]);
Paul Stewartadf79d82012-07-18 16:09:56 -0700890 service->OnPropertyChanged(flimflam::kEapKeyMgmtProperty);
Paul Stewart81426132012-05-16 10:05:10 -0700891
892 service->set_is_8021x(true);
893
894 // When this is an 802.1x-based service, set_eap should be called for
895 // all credential-carrying properties.
896 for (size_t i = 0; i < arraysize(eap_credential_properties); ++i) {
897 EXPECT_CALL(*service, set_eap(_)).Times(1);
898 service->OnPropertyChanged(eap_credential_properties[i]);
899 Mock::VerifyAndClearExpectations(service.get());
900 }
Paul Stewartadf79d82012-07-18 16:09:56 -0700901
902 // The key management property is a special case. While not strictly
903 // a credential, it can change which credentials are used. Therefore it
904 // should also trigger a call to set_eap();
905 EXPECT_CALL(*service, set_eap(_)).Times(1);
906 service->OnPropertyChanged(flimflam::kEapKeyMgmtProperty);
907 Mock::VerifyAndClearExpectations(service.get());
908
Paul Stewart81426132012-05-16 10:05:10 -0700909 EXPECT_CALL(*service, set_eap(_)).Times(0);
910 for (size_t i = 0; i < arraysize(eap_non_credential_properties); ++i)
911 service->OnPropertyChanged(eap_non_credential_properties[i]);
912}
913
Paul Stewartbc6e7392012-05-24 07:07:48 -0700914TEST_F(ServiceTest, Certification) {
915 EXPECT_FALSE(service_->eap_.remote_certification.size());
916
917 ScopedMockLog log;
918 EXPECT_CALL(log, Log(logging::LOG_WARNING, _,
919 HasSubstr("exceeds our maximum"))).Times(2);
920 string kSubject("foo");
921 EXPECT_FALSE(service_->AddEAPCertification(
922 kSubject, Service::kEAPMaxCertificationElements));
923 EXPECT_FALSE(service_->AddEAPCertification(
924 kSubject, Service::kEAPMaxCertificationElements + 1));
925 EXPECT_FALSE(service_->eap_.remote_certification.size());
926 Mock::VerifyAndClearExpectations(&log);
927
928 EXPECT_CALL(log,
929 Log(logging::LOG_INFO, _, HasSubstr("Received certification")))
930 .Times(1);
931 EXPECT_TRUE(service_->AddEAPCertification(
932 kSubject, Service::kEAPMaxCertificationElements - 1));
933 Mock::VerifyAndClearExpectations(&log);
934 EXPECT_EQ(Service::kEAPMaxCertificationElements,
935 service_->eap_.remote_certification.size());
936 for (size_t i = 0; i < Service::kEAPMaxCertificationElements - 1; ++i) {
937 EXPECT_TRUE(service_->eap_.remote_certification[i].empty());
938 }
939 EXPECT_EQ(kSubject, service_->eap_.remote_certification[
940 Service::kEAPMaxCertificationElements - 1]);
941
942 // Re-adding the same name in the same position should not generate a log.
943 EXPECT_CALL(log, Log(_, _, _)).Times(0);
944 EXPECT_TRUE(service_->AddEAPCertification(
945 kSubject, Service::kEAPMaxCertificationElements - 1));
946
947 // Replacing the item should generate a log message.
948 EXPECT_CALL(log,
949 Log(logging::LOG_INFO, _, HasSubstr("Received certification")))
950 .Times(1);
951 EXPECT_TRUE(service_->AddEAPCertification(
952 kSubject + "x", Service::kEAPMaxCertificationElements - 1));
953}
954
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700955} // namespace shill