blob: 24cd06caa048ffcf768eca4935c40ae26f62eaee [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
Chris Masone3bd3c8c2011-06-13 08:20:26 -070011#include <chromeos/dbus/service_constants.h>
mukesh agrawal1830fa12011-09-26 14:31:40 -070012#include <dbus-c++/dbus.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070013#include <gtest/gtest.h>
14#include <gmock/gmock.h>
15
16#include "shill/dbus_adaptor.h"
17#include "shill/ethernet_service.h"
Paul Stewart26b327e2011-10-19 11:38:09 -070018#include "shill/event_dispatcher.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070019#include "shill/manager.h"
Chris Masone95207da2011-06-29 16:50:49 -070020#include "shill/mock_adaptors.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070021#include "shill/mock_control.h"
Paul Stewart03dba0b2011-08-22 16:32:45 -070022#include "shill/mock_manager.h"
Darin Petkovba40dd32011-07-11 20:06:39 -070023#include "shill/mock_store.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070024#include "shill/property_store_unittest.h"
Chris Masone6515aab2011-10-12 16:19:09 -070025#include "shill/service_under_test.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070026
27using std::map;
28using std::string;
29using std::vector;
Darin Petkovba40dd32011-07-11 20:06:39 -070030using testing::_;
31using testing::AtLeast;
Paul Stewartd8ad3c42012-01-09 12:39:38 -080032using testing::DoAll;
Darin Petkovba40dd32011-07-11 20:06:39 -070033using testing::NiceMock;
34using testing::Return;
35using testing::StrictMock;
Paul Stewartd8ad3c42012-01-09 12:39:38 -080036using testing::SetArgumentPointee;
Darin Petkovba40dd32011-07-11 20:06:39 -070037using testing::Test;
Paul Stewart9f32d192012-01-30 20:37:50 -080038using testing::Values;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070039
40namespace shill {
41
42class ServiceTest : public PropertyStoreTest {
43 public:
Chris Masoneb925cc82011-06-22 15:39:57 -070044 ServiceTest()
Thieu Le3426c8f2012-01-11 17:35:11 -080045 : mock_manager_(control_interface(), dispatcher(), metrics(), glib()),
Chris Masone2176a882011-09-14 22:29:15 -070046 service_(new ServiceUnderTest(control_interface(),
47 dispatcher(),
Thieu Le3426c8f2012-01-11 17:35:11 -080048 metrics(),
Paul Stewart03dba0b2011-08-22 16:32:45 -070049 &mock_manager_)),
Chris Masone9d779932011-08-25 16:33:41 -070050 storage_id_(ServiceUnderTest::kStorageId) {
51 }
Chris Masoneb925cc82011-06-22 15:39:57 -070052
Chris Masone3bd3c8c2011-06-13 08:20:26 -070053 virtual ~ServiceTest() {}
Chris Masoneb925cc82011-06-22 15:39:57 -070054
55 protected:
Paul Stewart03dba0b2011-08-22 16:32:45 -070056 MockManager mock_manager_;
57 scoped_refptr<ServiceUnderTest> service_;
Chris Masone34af2182011-08-22 11:59:36 -070058 string storage_id_;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070059};
60
Darin Petkovba40dd32011-07-11 20:06:39 -070061TEST_F(ServiceTest, Constructor) {
62 EXPECT_TRUE(service_->save_credentials_);
63 EXPECT_EQ(Service::kCheckPortalAuto, service_->check_portal_);
64}
65
Chris Masonea8a2c252011-06-27 22:16:30 -070066TEST_F(ServiceTest, GetProperties) {
67 map<string, ::DBus::Variant> props;
68 Error error(Error::kInvalidProperty, "");
69 {
70 ::DBus::Error dbus_error;
71 string expected("portal_list");
mukesh agrawalde29fa82011-09-16 16:16:36 -070072 service_->mutable_store()->SetStringProperty(flimflam::kCheckPortalProperty,
73 expected,
74 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -070075 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -070076 ASSERT_FALSE(props.find(flimflam::kCheckPortalProperty) == props.end());
77 EXPECT_EQ(props[flimflam::kCheckPortalProperty].reader().get_string(),
78 expected);
79 }
80 {
81 ::DBus::Error dbus_error;
82 bool expected = true;
Thieu Le284fe792012-01-31 17:53:19 -080083 service_->set_favorite(true);
mukesh agrawalde29fa82011-09-16 16:16:36 -070084 service_->mutable_store()->SetBoolProperty(flimflam::kAutoConnectProperty,
85 expected,
86 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -070087 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -070088 ASSERT_FALSE(props.find(flimflam::kAutoConnectProperty) == props.end());
89 EXPECT_EQ(props[flimflam::kAutoConnectProperty].reader().get_bool(),
90 expected);
91 }
92 {
93 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -070094 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -070095 ASSERT_FALSE(props.find(flimflam::kConnectableProperty) == props.end());
96 EXPECT_EQ(props[flimflam::kConnectableProperty].reader().get_bool(), false);
97 }
98 {
99 ::DBus::Error dbus_error;
100 int32 expected = 127;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700101 service_->mutable_store()->SetInt32Property(flimflam::kPriorityProperty,
102 expected,
103 &error);
Chris Masone27c4aa52011-07-02 13:10:14 -0700104 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700105 ASSERT_FALSE(props.find(flimflam::kPriorityProperty) == props.end());
106 EXPECT_EQ(props[flimflam::kPriorityProperty].reader().get_int32(),
107 expected);
108 }
Chris Masone95207da2011-06-29 16:50:49 -0700109 {
110 ::DBus::Error dbus_error;
Chris Masone27c4aa52011-07-02 13:10:14 -0700111 DBusAdaptor::GetProperties(service_->store(), &props, &dbus_error);
Chris Masone95207da2011-06-29 16:50:49 -0700112 ASSERT_FALSE(props.find(flimflam::kDeviceProperty) == props.end());
113 EXPECT_EQ(props[flimflam::kDeviceProperty].reader().get_string(),
Paul Stewart03dba0b2011-08-22 16:32:45 -0700114 string(ServiceUnderTest::kRpcId));
Chris Masone95207da2011-06-29 16:50:49 -0700115 }
Chris Masonea8a2c252011-06-27 22:16:30 -0700116}
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700117
Chris Masonea8a2c252011-06-27 22:16:30 -0700118TEST_F(ServiceTest, Dispatch) {
119 {
120 ::DBus::Error error;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700121 EXPECT_TRUE(DBusAdaptor::DispatchOnType(service_->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -0700122 flimflam::kSaveCredentialsProperty,
123 PropertyStoreTest::kBoolV,
124 &error));
125 }
126 {
127 ::DBus::Error error;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700128 EXPECT_TRUE(DBusAdaptor::DispatchOnType(service_->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -0700129 flimflam::kPriorityProperty,
130 PropertyStoreTest::kInt32V,
131 &error));
132 }
133 {
134 ::DBus::Error error;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700135 EXPECT_TRUE(DBusAdaptor::DispatchOnType(service_->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -0700136 flimflam::kEAPEAPProperty,
137 PropertyStoreTest::kStringV,
138 &error));
139 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700140 // Ensure that an attempt to write a R/O property returns InvalidArgs error.
Chris Masonea8a2c252011-06-27 22:16:30 -0700141 {
142 ::DBus::Error error;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700143 EXPECT_FALSE(DBusAdaptor::DispatchOnType(service_->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -0700144 flimflam::kFavoriteProperty,
145 PropertyStoreTest::kBoolV,
146 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700147 EXPECT_EQ(invalid_args(), error.name());
Chris Masonea8a2c252011-06-27 22:16:30 -0700148 }
Thieu Le284fe792012-01-31 17:53:19 -0800149 {
150 ::DBus::Error error;
151 service_->set_favorite(true);
152 EXPECT_TRUE(DBusAdaptor::DispatchOnType(service_->mutable_store(),
153 flimflam::kAutoConnectProperty,
154 PropertyStoreTest::kBoolV,
155 &error));
156 }
157 {
158 ::DBus::Error error;
159 service_->set_favorite(false);
160 EXPECT_FALSE(DBusAdaptor::DispatchOnType(service_->mutable_store(),
161 flimflam::kAutoConnectProperty,
162 PropertyStoreTest::kBoolV,
163 &error));
164 EXPECT_EQ(invalid_args(), error.name());
165 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700166}
167
Darin Petkovba40dd32011-07-11 20:06:39 -0700168TEST_F(ServiceTest, Load) {
169 NiceMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700170 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
171 EXPECT_CALL(storage, GetString(storage_id_, _, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700172 .Times(AtLeast(1))
173 .WillRepeatedly(Return(true));
Chris Masone9d779932011-08-25 16:33:41 -0700174 EXPECT_TRUE(service_->Load(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700175}
176
177TEST_F(ServiceTest, LoadFail) {
178 StrictMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700179 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(false));
Chris Masone9d779932011-08-25 16:33:41 -0700180 EXPECT_FALSE(service_->Load(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700181}
182
183TEST_F(ServiceTest, SaveString) {
184 MockStore storage;
185 static const char kKey[] = "test-key";
186 static const char kData[] = "test-data";
Chris Masone34af2182011-08-22 11:59:36 -0700187 EXPECT_CALL(storage, SetString(storage_id_, kKey, kData))
Darin Petkovba40dd32011-07-11 20:06:39 -0700188 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700189 service_->SaveString(&storage, storage_id_, kKey, kData, false, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700190}
191
192TEST_F(ServiceTest, SaveStringCrypted) {
193 MockStore storage;
194 static const char kKey[] = "test-key";
195 static const char kData[] = "test-data";
Chris Masone34af2182011-08-22 11:59:36 -0700196 EXPECT_CALL(storage, SetCryptedString(storage_id_, kKey, kData))
Darin Petkovba40dd32011-07-11 20:06:39 -0700197 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700198 service_->SaveString(&storage, storage_id_, kKey, kData, true, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700199}
200
201TEST_F(ServiceTest, SaveStringDontSave) {
202 MockStore storage;
203 static const char kKey[] = "test-key";
Chris Masone34af2182011-08-22 11:59:36 -0700204 EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
Darin Petkovba40dd32011-07-11 20:06:39 -0700205 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700206 service_->SaveString(&storage, storage_id_, kKey, "data", false, false);
Darin Petkovba40dd32011-07-11 20:06:39 -0700207}
208
209TEST_F(ServiceTest, SaveStringEmpty) {
210 MockStore storage;
211 static const char kKey[] = "test-key";
Chris Masone34af2182011-08-22 11:59:36 -0700212 EXPECT_CALL(storage, DeleteKey(storage_id_, kKey))
Darin Petkovba40dd32011-07-11 20:06:39 -0700213 .WillOnce(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700214 service_->SaveString(&storage, storage_id_, kKey, "", true, true);
Darin Petkovba40dd32011-07-11 20:06:39 -0700215}
216
217TEST_F(ServiceTest, Save) {
218 NiceMock<MockStore> storage;
Chris Masone34af2182011-08-22 11:59:36 -0700219 EXPECT_CALL(storage, SetString(storage_id_, _, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700220 .Times(AtLeast(1))
221 .WillRepeatedly(Return(true));
Chris Masone34af2182011-08-22 11:59:36 -0700222 EXPECT_CALL(storage, DeleteKey(storage_id_, _))
Darin Petkovba40dd32011-07-11 20:06:39 -0700223 .Times(AtLeast(1))
224 .WillRepeatedly(Return(true));
Chris Masone9d779932011-08-25 16:33:41 -0700225 EXPECT_TRUE(service_->Save(&storage));
Darin Petkovba40dd32011-07-11 20:06:39 -0700226}
227
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800228TEST_F(ServiceTest, Unload) {
229 NiceMock<MockStore> storage;
230 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
231 static const string string_value("value");
232 EXPECT_CALL(storage, GetString(storage_id_, _, _))
233 .Times(AtLeast(1))
234 .WillRepeatedly(DoAll(SetArgumentPointee<2>(string_value), Return(true)));
235 ASSERT_TRUE(service_->Load(&storage));
236 // TODO(pstew): A single string property in the service is tested as
237 // a sentinel that properties are being set and reset at the rit times.
238 // However, since property load/store is essentially a manual process,
239 // it is error prone and should either be exhaustively unit-tested or
240 // a generic framework for registering loaded/stored properties should
241 // be created. crosbug.com/24859
242 EXPECT_EQ(string_value, service_->ui_data_);
243 service_->Unload();
244 EXPECT_EQ(string(""), service_->ui_data_);
245}
246
Paul Stewart03dba0b2011-08-22 16:32:45 -0700247TEST_F(ServiceTest, State) {
248 EXPECT_EQ(Service::kStateUnknown, service_->state());
249 EXPECT_EQ(Service::kFailureUnknown, service_->failure());
250
mukesh agrawal00917ce2011-11-22 23:56:55 +0000251 ServiceRefPtr service_ref(service_);
mukesh agrawalf2f68a52011-09-01 12:15:48 -0700252
253 // TODO(quiche): make this EXPECT_CALL work (crosbug.com/20154)
254 // EXPECT_CALL(*dynamic_cast<ServiceMockAdaptor *>(service_->adaptor_.get()),
255 // EmitStringChanged(flimflam::kStateProperty, _));
Paul Stewart03dba0b2011-08-22 16:32:45 -0700256 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
257 service_->SetState(Service::kStateConnected);
258 // A second state change shouldn't cause another update
259 service_->SetState(Service::kStateConnected);
260
261 EXPECT_EQ(Service::kStateConnected, service_->state());
262 EXPECT_EQ(Service::kFailureUnknown, service_->failure());
263 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
264 service_->SetState(Service::kStateDisconnected);
265
266 EXPECT_CALL(mock_manager_, UpdateService(service_ref));
267 service_->SetFailure(Service::kFailureOutOfRange);
268
269 EXPECT_EQ(Service::kStateFailure, service_->state());
270 EXPECT_EQ(Service::kFailureOutOfRange, service_->failure());
271}
272
Darin Petkovb100ae72011-08-24 16:19:45 -0700273TEST_F(ServiceTest, ActivateCellularModem) {
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500274 MockReturner returner;
275 EXPECT_CALL(returner, Return()).Times(0);
276 EXPECT_CALL(returner, ReturnError(_));
Darin Petkovb100ae72011-08-24 16:19:45 -0700277 Error error;
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500278 service_->ActivateCellularModem("Carrier", &returner);
Darin Petkovb100ae72011-08-24 16:19:45 -0700279}
280
mukesh agrawal00917ce2011-11-22 23:56:55 +0000281TEST_F(ServiceTest, MakeFavorite) {
282 EXPECT_FALSE(service_->favorite());
283 EXPECT_FALSE(service_->auto_connect());
284
285 service_->MakeFavorite();
286 EXPECT_TRUE(service_->favorite());
287 EXPECT_TRUE(service_->auto_connect());
288}
289
290TEST_F(ServiceTest, ReMakeFavorite) {
291 service_->MakeFavorite();
292 EXPECT_TRUE(service_->favorite());
293 EXPECT_TRUE(service_->auto_connect());
294
295 service_->set_auto_connect(false);
296 service_->MakeFavorite();
297 EXPECT_TRUE(service_->favorite());
298 EXPECT_FALSE(service_->auto_connect());
299}
300
mukesh agrawal76d13882012-01-12 15:23:11 -0800301TEST_F(ServiceTest, IsAutoConnectable) {
302 service_->set_connectable(true);
303 EXPECT_TRUE(service_->IsAutoConnectable());
304
mukesh agrawaladb68482012-01-17 16:31:51 -0800305 // We should not auto-connect to a Service that a user has
306 // deliberately disconnected.
307 Error error;
308 service_->Disconnect(&error);
309 EXPECT_FALSE(service_->IsAutoConnectable());
310
311 // But if the Service is reloaded, it is eligible for auto-connect
312 // again.
313 NiceMock<MockStore> storage;
314 EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
315 EXPECT_TRUE(service_->Load(&storage));
316 EXPECT_TRUE(service_->IsAutoConnectable());
317
318 // A deliberate Connect should also re-enable auto-connect.
319 service_->Disconnect(&error);
320 EXPECT_FALSE(service_->IsAutoConnectable());
321 service_->Connect(&error);
322 EXPECT_TRUE(service_->IsAutoConnectable());
323
324 // TODO(quiche): After we have resume handling in place, test that
325 // we re-enable auto-connect on resume. crosbug.com/25213
326
mukesh agrawal76d13882012-01-12 15:23:11 -0800327 service_->SetState(Service::kStateConnected);
328 EXPECT_FALSE(service_->IsAutoConnectable());
329
330 service_->SetState(Service::kStateAssociating);
331 EXPECT_FALSE(service_->IsAutoConnectable());
332}
333
Paul Stewart9f32d192012-01-30 20:37:50 -0800334// Make sure a property is registered as a write only property
335// by reading and comparing all string properties returned on the store.
336// Subtle: We need to convert the test argument back and forth between
337// string and ::DBus::Variant because this is the parameter type that
338// our supeclass (PropertyStoreTest) is declared with.
339class ReadOnlyServicePropertyTest : public ServiceTest {};
340TEST_P(ReadOnlyServicePropertyTest, PropertyWriteOnly) {
341 ReadablePropertyConstIterator<string> it =
342 (service_->store()).GetStringPropertiesIter();
343 string property(GetParam().reader().get_string());
344 for( ; !it.AtEnd(); it.Advance())
345 EXPECT_NE(it.Key(), property);
346}
347
348INSTANTIATE_TEST_CASE_P(
349 ReadOnlyServicePropertyTestInstance,
350 ReadOnlyServicePropertyTest,
351 Values(
352 DBusAdaptor::StringToVariant(flimflam::kEapPrivateKeyPasswordProperty),
353 DBusAdaptor::StringToVariant(flimflam::kEapPasswordProperty)));
354
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700355} // namespace shill