blob: fc1a0b948ab6a205c8def21eb5e5a8960d15cd83 [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 Stewart03dba0b2011-08-22 16:32:45 -070023#include "shill/mock_manager.h"
Darin Petkovba40dd32011-07-11 20:06:39 -070024#include "shill/mock_store.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070025#include "shill/property_store_unittest.h"
Chris Masone6515aab2011-10-12 16:19:09 -070026#include "shill/service_under_test.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070027
Eric Shienbrood9a245532012-03-07 14:20:39 -050028using base::Bind;
29using base::Unretained;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070030using std::map;
31using std::string;
32using std::vector;
Darin Petkovba40dd32011-07-11 20:06:39 -070033using testing::_;
34using testing::AtLeast;
Paul Stewartd8ad3c42012-01-09 12:39:38 -080035using testing::DoAll;
Darin Petkovba40dd32011-07-11 20:06:39 -070036using testing::NiceMock;
37using testing::Return;
38using testing::StrictMock;
Paul Stewartd8ad3c42012-01-09 12:39:38 -080039using testing::SetArgumentPointee;
Darin Petkovba40dd32011-07-11 20:06:39 -070040using testing::Test;
Paul Stewart9f32d192012-01-30 20:37:50 -080041using testing::Values;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070042
43namespace shill {
44
45class ServiceTest : public PropertyStoreTest {
46 public:
Chris Masoneb925cc82011-06-22 15:39:57 -070047 ServiceTest()
Thieu Le3426c8f2012-01-11 17:35:11 -080048 : mock_manager_(control_interface(), dispatcher(), metrics(), glib()),
Chris Masone2176a882011-09-14 22:29:15 -070049 service_(new ServiceUnderTest(control_interface(),
50 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -080051 metrics(),
Paul Stewart03dba0b2011-08-22 16:32:45 -070052 &mock_manager_)),
Chris Masone9d779932011-08-25 16:33:41 -070053 storage_id_(ServiceUnderTest::kStorageId) {
54 }
Chris Masoneb925cc82011-06-22 15:39:57 -070055
Chris Masone3bd3c8c2011-06-13 08:20:26 -070056 virtual ~ServiceTest() {}
Chris Masoneb925cc82011-06-22 15:39:57 -070057
Eric Shienbrood9a245532012-03-07 14:20:39 -050058 MOCK_METHOD1(TestCallback, void(const Error &error));
59
Chris Masoneb925cc82011-06-22 15:39:57 -070060 protected:
Eric Shienbrood9a245532012-03-07 14:20:39 -050061
Paul Stewart03dba0b2011-08-22 16:32:45 -070062 MockManager mock_manager_;
63 scoped_refptr<ServiceUnderTest> service_;
Chris Masone34af2182011-08-22 11:59:36 -070064 string storage_id_;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070065};
66
Darin Petkovba40dd32011-07-11 20:06:39 -070067TEST_F(ServiceTest, Constructor) {
68 EXPECT_TRUE(service_->save_credentials_);
69 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
70}
71
Chris Masonea8a2c252011-06-27 22:16:30 -070072TEST_F(ServiceTest, GetProperties) {
73 map<string, ::DBus::Variant> props;
74 Error error(Error::kInvalidProperty, "");
75 {
76 ::DBus::Error dbus_error;
77 string expected("portal_list");
mukesh agrawalde29fa82011-09-16 16:16:36 -070078 service_->mutable_store()->SetStringProperty(flimflam::kCheckPortalProperty,
79 expected,
80 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -070081 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -070082 ASSERT_FALSE(props.find(flimflam::kCheckPortalProperty) == props.end());
83 EXPECT_EQ(props[flimflam::kCheckPortalProperty].reader().get_string(),
84 expected);
85 }
86 {
87 ::DBus::Error dbus_error;
88 bool expected = true;
Thieu Le284fe792012-01-31 17:53:19 -080089 service_->set_favorite(true);
mukesh agrawalde29fa82011-09-16 16:16:36 -070090 service_->mutable_store()->SetBoolProperty(flimflam::kAutoConnectProperty,
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::kAutoConnectProperty) == props.end());
95 EXPECT_EQ(props[flimflam::kAutoConnectProperty].reader().get_bool(),
96 expected);
97 }
98 {
99 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -0700100 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700101 ASSERT_FALSE(props.find(flimflam::kConnectableProperty) == props.end());
102 EXPECT_EQ(props[flimflam::kConnectableProperty].reader().get_bool(), false);
103 }
104 {
105 ::DBus::Error dbus_error;
106 int32 expected = 127;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700107 service_->mutable_store()->SetInt32Property(flimflam::kPriorityProperty,
108 expected,
109 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700110 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700111 ASSERT_FALSE(props.find(flimflam::kPriorityProperty) == props.end());
112 EXPECT_EQ(props[flimflam::kPriorityProperty].reader().get_int32(),
113 expected);
114 }
Chris Masone95207da2011-06-29 16:50:49 -0700115 {
116 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -0700117 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masone95207da2011-06-29 16:50:49 -0700118 ASSERT_FALSE(props.find(flimflam::kDeviceProperty) == props.end());
119 EXPECT_EQ(props[flimflam::kDeviceProperty].reader().get_string(),
Paul Stewart03dba0b2011-08-22 16:32:45 -0700120 string(ServiceUnderTest::kRpcId));
Chris Masone95207da2011-06-29 16:50:49 -0700121 }
Chris Masonea8a2c252011-06-27 22:16:30 -0700122}
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700123
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800124TEST_F(ServiceTest, SetProperty) {
Chris Masonea8a2c252011-06-27 22:16:30 -0700125 {
126 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800127 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
128 flimflam::kSaveCredentialsProperty,
129 PropertyStoreTest::kBoolV,
130 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700131 }
132 {
133 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800134 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
135 flimflam::kPriorityProperty,
136 PropertyStoreTest::kInt32V,
137 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700138 }
139 {
140 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800141 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
142 flimflam::kEAPEAPProperty,
143 PropertyStoreTest::kStringV,
144 &error));
Chris Masonea8a2c252011-06-27 22:16:30 -0700145 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700146 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
Chris Masonea8a2c252011-06-27 22:16:30 -0700147 {
148 ::DBus::Error error;
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800149 EXPECT_FALSE(DBusAdaptor::SetProperty(service_->mutable_store(),
150 flimflam::kFavoriteProperty,
151 PropertyStoreTest::kBoolV,
152 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700153 EXPECT_EQ(invalid_args(), error.name());
Chris Masonea8a2c252011-06-27 22:16:30 -0700154 }
Thieu Le284fe792012-01-31 17:53:19 -0800155 {
156 ::DBus::Error error;
157 service_->set_favorite(true);
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800158 EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
159 flimflam::kAutoConnectProperty,
160 PropertyStoreTest::kBoolV,
161 &error));
Thieu Le284fe792012-01-31 17:53:19 -0800162 }
163 {
164 ::DBus::Error error;
165 service_->set_favorite(false);
mukesh agrawal6bb9e7c2012-01-30 14:57:54 -0800166 EXPECT_FALSE(DBusAdaptor::SetProperty(service_->mutable_store(),
167 flimflam::kAutoConnectProperty,
168 PropertyStoreTest::kBoolV,
169 &error));
Thieu Le284fe792012-01-31 17:53:19 -0800170 EXPECT_EQ(invalid_args(), error.name());
171 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700172}
173
Darin Petkovba40dd32011-07-11 20:06:39 -0700174TEST_F(ServiceTest, Load) {
175 NiceMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700176 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
177 EXPECT_CALL(storage, GetString(storage_id_, _, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700178 .Times(AtLeast(1))
179 .WillRepeatedly(Return(true));
Chris Masone9d779932011-08-25 16:33:41 -0700180 EXPECT_TRUE(service_->Load(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700181}
182
183TEST_F(ServiceTest, LoadFail) {
184 StrictMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700185 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(false));
Chris Masone9d779932011-08-25 16:33:41 -0700186 EXPECT_FALSE(service_->Load(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700187}
188
189TEST_F(ServiceTest, SaveString) {
190 MockStore storage;
191 static const char kKey[] = "test-key";
192 static const char kData[] = "test-data";
Chris Masone34af2182011-08-22 11:59:36 -0700193 EXPECT_CALL(storage, SetString(storage_id_, kKey, kData))
Darin Petkovba40dd32011-07-11 20:06:39 -0700194 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700195 service_->SaveString(&storage, storage_id_, kKey, kData, false, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700196}
197
198TEST_F(ServiceTest, SaveStringCrypted) {
199 MockStore storage;
200 static const char kKey[] = "test-key";
201 static const char kData[] = "test-data";
Chris Masone34af2182011-08-22 11:59:36 -0700202 EXPECT_CALL(storage, SetCryptedString(storage_id_, kKey, kData))
Darin Petkovba40dd32011-07-11 20:06:39 -0700203 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700204 service_->SaveString(&storage, storage_id_, kKey, kData, true, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700205}
206
207TEST_F(ServiceTest, SaveStringDontSave) {
208 MockStore storage;
209 static const char kKey[] = "test-key";
Chris Masone34af2182011-08-22 11:59:36 -0700210 EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
Darin Petkovba40dd32011-07-11 20:06:39 -0700211 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700212 service_->SaveString(&storage, storage_id_, kKey, "data", false, false);
Darin Petkovba40dd32011-07-11 20:06:39 -0700213}
214
215TEST_F(ServiceTest, SaveStringEmpty) {
216 MockStore storage;
217 static const char kKey[] = "test-key";
Chris Masone34af2182011-08-22 11:59:36 -0700218 EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
Darin Petkovba40dd32011-07-11 20:06:39 -0700219 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700220 service_->SaveString(&storage, storage_id_, kKey, "", true, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700221}
222
223TEST_F(ServiceTest, Save) {
224 NiceMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700225 EXPECT_CALL(storage, SetString(storage_id_, _, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700226 .Times(AtLeast(1))
227 .WillRepeatedly(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700228 EXPECT_CALL(storage, DeleteKey(storage_id_, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700229 .Times(AtLeast(1))
230 .WillRepeatedly(Return(true));
Chris Masone9d779932011-08-25 16:33:41 -0700231 EXPECT_TRUE(service_->Save(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700232}
233
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800234TEST_F(ServiceTest, Unload) {
235 NiceMock<MockStore> storage;
236 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
237 static const string string_value("value");
238 EXPECT_CALL(storage, GetString(storage_id_, _, _))
239 .Times(AtLeast(1))
240 .WillRepeatedly(DoAll(SetArgumentPointee<2>(string_value), Return(true)));
241 ASSERT_TRUE(service_->Load(&storage));
242 // TODO(pstew): A single string property in the service is tested as
243 // a sentinel that properties are being set and reset at the rit times.
244 // However, since property load/store is essentially a manual process,
245 // it is error prone and should either be exhaustively unit-tested or
246 // a generic framework for registering loaded/stored properties should
247 // be created. crosbug.com/24859
248 EXPECT_EQ(string_value, service_->ui_data_);
249 service_->Unload();
250 EXPECT_EQ(string(""), service_->ui_data_);
251}
252
Paul Stewart03dba0b2011-08-22 16:32:45 -0700253TEST_F(ServiceTest, State) {
254 EXPECT_EQ(Service::kStateUnknown, service_->state());
255 EXPECT_EQ(Service::kFailureUnknown, service_->failure());
256
mukesh agrawal00917ce2011-11-22 23:56:55 +0000257 ServiceRefPtr service_ref(service_);
mukesh agrawalf2f68a52011-09-01 12:15:48 -0700258
259 // TODO(quiche): make this EXPECT_CALL work (crosbug.com/20154)
260 // EXPECT_CALL(*dynamic_cast<ServiceMockAdaptor *>(service_->adaptor_.get()),
261 // EmitStringChanged(flimflam::kStateProperty, _));
Paul Stewart03dba0b2011-08-22 16:32:45 -0700262 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
263 service_->SetState(Service::kStateConnected);
264 // A second state change shouldn't cause another update
265 service_->SetState(Service::kStateConnected);
266
267 EXPECT_EQ(Service::kStateConnected, service_->state());
268 EXPECT_EQ(Service::kFailureUnknown, service_->failure());
269 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
270 service_->SetState(Service::kStateDisconnected);
271
272 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
273 service_->SetFailure(Service::kFailureOutOfRange);
274
275 EXPECT_EQ(Service::kStateFailure, service_->state());
276 EXPECT_EQ(Service::kFailureOutOfRange, service_->failure());
277}
278
Darin Petkovb100ae72011-08-24 16:19:45 -0700279TEST_F(ServiceTest, ActivateCellularModem) {
Eric Shienbrood9a245532012-03-07 14:20:39 -0500280 ResultCallback callback =
281 Bind(&ServiceTest::TestCallback, Unretained(this));
282 EXPECT_CALL(*this, TestCallback(_)).Times(0);
Darin Petkovb100ae72011-08-24 16:19:45 -0700283 Error error;
Eric Shienbrood9a245532012-03-07 14:20:39 -0500284 service_->ActivateCellularModem("Carrier", &error, callback);
285 EXPECT_TRUE(error.IsFailure());
Darin Petkovb100ae72011-08-24 16:19:45 -0700286}
287
mukesh agrawal00917ce2011-11-22 23:56:55 +0000288TEST_F(ServiceTest, MakeFavorite) {
289 EXPECT_FALSE(service_->favorite());
290 EXPECT_FALSE(service_->auto_connect());
291
292 service_->MakeFavorite();
293 EXPECT_TRUE(service_->favorite());
294 EXPECT_TRUE(service_->auto_connect());
295}
296
297TEST_F(ServiceTest, ReMakeFavorite) {
298 service_->MakeFavorite();
299 EXPECT_TRUE(service_->favorite());
300 EXPECT_TRUE(service_->auto_connect());
301
302 service_->set_auto_connect(false);
303 service_->MakeFavorite();
304 EXPECT_TRUE(service_->favorite());
305 EXPECT_FALSE(service_->auto_connect());
306}
307
mukesh agrawal76d13882012-01-12 15:23:11 -0800308TEST_F(ServiceTest, IsAutoConnectable) {
mukesh agrawalbf14e942012-03-02 14:36:34 -0800309 const char *reason;
mukesh agrawal76d13882012-01-12 15:23:11 -0800310 service_->set_connectable(true);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800311 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawal76d13882012-01-12 15:23:11 -0800312
mukesh agrawaladb68482012-01-17 16:31:51 -0800313 // We should not auto-connect to a Service that a user has
314 // deliberately disconnected.
315 Error error;
316 service_->Disconnect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800317 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
318 EXPECT_STREQ(Service::kAutoConnExplicitDisconnect, reason);
mukesh agrawaladb68482012-01-17 16:31:51 -0800319
320 // But if the Service is reloaded, it is eligible for auto-connect
321 // again.
322 NiceMock<MockStore> storage;
323 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
324 EXPECT_TRUE(service_->Load(&storage));
mukesh agrawalbf14e942012-03-02 14:36:34 -0800325 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800326
327 // A deliberate Connect should also re-enable auto-connect.
328 service_->Disconnect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800329 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800330 service_->Connect(&error);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800331 EXPECT_TRUE(service_->IsAutoConnectable(&reason));
mukesh agrawaladb68482012-01-17 16:31:51 -0800332
333 // TODO(quiche): After we have resume handling in place, test that
334 // we re-enable auto-connect on resume. crosbug.com/25213
335
mukesh agrawal76d13882012-01-12 15:23:11 -0800336 service_->SetState(Service::kStateConnected);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800337 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
338 EXPECT_STREQ(Service::kAutoConnConnected, reason);
mukesh agrawal76d13882012-01-12 15:23:11 -0800339
340 service_->SetState(Service::kStateAssociating);
mukesh agrawalbf14e942012-03-02 14:36:34 -0800341 EXPECT_FALSE(service_->IsAutoConnectable(&reason));
342 EXPECT_STREQ(Service::kAutoConnConnecting, reason);
mukesh agrawal76d13882012-01-12 15:23:11 -0800343}
344
Paul Stewart9f32d192012-01-30 20:37:50 -0800345// Make sure a property is registered as a write only property
346// by reading and comparing all string properties returned on the store.
347// Subtle: We need to convert the test argument back and forth between
348// string and ::DBus::Variant because this is the parameter type that
349// our supeclass (PropertyStoreTest) is declared with.
350class ReadOnlyServicePropertyTest : public ServiceTest {};
351TEST_P(ReadOnlyServicePropertyTest, PropertyWriteOnly) {
352 ReadablePropertyConstIterator<string> it =
353 (service_->store()).GetStringPropertiesIter();
354 string property(GetParam().reader().get_string());
355 for( ; !it.AtEnd(); it.Advance())
356 EXPECT_NE(it.Key(), property);
357}
358
359INSTANTIATE_TEST_CASE_P(
360 ReadOnlyServicePropertyTestInstance,
361 ReadOnlyServicePropertyTest,
362 Values(
363 DBusAdaptor::StringToVariant(flimflam::kEapPrivateKeyPasswordProperty),
364 DBusAdaptor::StringToVariant(flimflam::kEapPasswordProperty)));
365
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700366} // namespace shill