blob: 05b2765c0c8daef74ca72b8ad7da9a86d62d922b [file] [log] [blame]
Chris Masone9be4a9d2011-05-16 15:44:09 -07001// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Chris Masone3bd3c8c2011-06-13 08:20:26 -07004
5#include "shill/manager.h"
6
Chris Masone6791a432011-07-12 13:23:19 -07007#include <set>
8
Chris Masone9be4a9d2011-05-16 15:44:09 -07009#include <glib.h>
10
Chris Masone9be4a9d2011-05-16 15:44:09 -070011#include <base/logging.h>
Paul Stewart5dc40aa2011-10-28 19:43:43 -070012#include <base/memory/scoped_temp_dir.h>
Chris Masone6791a432011-07-12 13:23:19 -070013#include <base/stl_util-inl.h>
Paul Stewart5dc40aa2011-10-28 19:43:43 -070014#include <base/stringprintf.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070015#include <chromeos/dbus/service_constants.h>
Chris Masone7156c922011-08-23 20:36:21 -070016#include <gmock/gmock.h>
Chris Masone2ae797d2011-08-23 20:41:00 -070017#include <gtest/gtest.h>
Chris Masone9be4a9d2011-05-16 15:44:09 -070018
mukesh agrawal32399322011-09-01 10:53:43 -070019#include "shill/adaptor_interfaces.h"
Chris Masone6515aab2011-10-12 16:19:09 -070020#include "shill/ephemeral_profile.h"
mukesh agrawal32399322011-09-01 10:53:43 -070021#include "shill/error.h"
Chris Masone6515aab2011-10-12 16:19:09 -070022#include "shill/glib.h"
23#include "shill/key_file_store.h"
mukesh agrawal7a4e4002011-09-06 11:26:05 -070024#include "shill/key_value_store.h"
mukesh agrawal32399322011-09-01 10:53:43 -070025#include "shill/mock_adaptors.h"
Chris Masoned7732e42011-05-20 11:08:56 -070026#include "shill/mock_control.h"
Chris Masone9be4a9d2011-05-16 15:44:09 -070027#include "shill/mock_device.h"
Chris Masone7aa5f902011-07-11 11:13:35 -070028#include "shill/mock_glib.h"
29#include "shill/mock_profile.h"
Chris Masone9be4a9d2011-05-16 15:44:09 -070030#include "shill/mock_service.h"
Chris Masoneb9c00592011-10-06 13:10:39 -070031#include "shill/mock_store.h"
mukesh agrawal7a4e4002011-09-06 11:26:05 -070032#include "shill/mock_wifi.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070033#include "shill/property_store_unittest.h"
Chris Masone6515aab2011-10-12 16:19:09 -070034#include "shill/service_under_test.h"
mukesh agrawal7a4e4002011-09-06 11:26:05 -070035#include "shill/wifi_service.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070036
37using std::map;
Chris Masone6791a432011-07-12 13:23:19 -070038using std::set;
Chris Masone3bd3c8c2011-06-13 08:20:26 -070039using std::string;
40using std::vector;
41
Chris Masone9be4a9d2011-05-16 15:44:09 -070042namespace shill {
Chris Masone9be4a9d2011-05-16 15:44:09 -070043using ::testing::_;
Chris Masone6515aab2011-10-12 16:19:09 -070044using ::testing::AnyNumber;
Paul Stewart22aa71b2011-09-16 12:15:11 -070045using ::testing::Ne;
Chris Masone9be4a9d2011-05-16 15:44:09 -070046using ::testing::NiceMock;
47using ::testing::Return;
Chris Masone9d779932011-08-25 16:33:41 -070048using ::testing::Test;
Chris Masone9be4a9d2011-05-16 15:44:09 -070049
Chris Masone3bd3c8c2011-06-13 08:20:26 -070050class ManagerTest : public PropertyStoreTest {
Chris Masone9be4a9d2011-05-16 15:44:09 -070051 public:
Chris Masone3c3f6a12011-07-01 10:01:41 -070052 ManagerTest()
Paul Stewart22aa71b2011-09-16 12:15:11 -070053 : mock_wifi_(new NiceMock<MockWiFi>(control_interface(),
mukesh agrawal7a4e4002011-09-06 11:26:05 -070054 dispatcher(),
55 manager(),
56 "wifi0",
57 "addr4",
Paul Stewart22aa71b2011-09-16 12:15:11 -070058 4)) {
59 mock_devices_.push_back(new NiceMock<MockDevice>(control_interface(),
60 dispatcher(),
61 manager(),
62 "null0",
63 "addr0",
64 0));
65 mock_devices_.push_back(new NiceMock<MockDevice>(control_interface(),
66 dispatcher(),
67 manager(),
68 "null1",
69 "addr1",
70 1));
71 mock_devices_.push_back(new NiceMock<MockDevice>(control_interface(),
72 dispatcher(),
73 manager(),
74 "null2",
75 "addr2",
76 2));
Paul Stewart5dc40aa2011-10-28 19:43:43 -070077 manager()->connect_profiles_to_rpc_ = false;
Chris Masone3c3f6a12011-07-01 10:01:41 -070078 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -070079 virtual ~ManagerTest() {}
Chris Masone9be4a9d2011-05-16 15:44:09 -070080
Paul Stewartfdd16072011-09-16 12:41:35 -070081 bool IsDeviceRegistered(const DeviceRefPtr &device,
82 Technology::Identifier tech) {
Chris Masonec1e50412011-06-07 13:04:53 -070083 vector<DeviceRefPtr> devices;
Chris Masone9d779932011-08-25 16:33:41 -070084 manager()->FilterByTechnology(tech, &devices);
Chris Masone2b105542011-06-22 10:58:09 -070085 return (devices.size() == 1 && devices[0].get() == device.get());
Chris Masone9be4a9d2011-05-16 15:44:09 -070086 }
Paul Stewart22aa71b2011-09-16 12:15:11 -070087 bool ServiceOrderIs(ServiceRefPtr svc1, ServiceRefPtr svc2);
Chris Masone9be4a9d2011-05-16 15:44:09 -070088
Paul Stewarta849a3d2011-11-03 05:54:09 -070089 void AdoptProfile(Manager *manager, ProfileRefPtr profile) {
90 manager->profiles_.push_back(profile);
91 }
92
Chris Masone6515aab2011-10-12 16:19:09 -070093 Profile *CreateProfileForManager(Manager *manager, GLib *glib) {
94 Profile::Identifier id("rather", "irrelevant");
95 scoped_ptr<Profile> profile(new Profile(control_interface(),
96 manager,
97 id,
98 "",
99 false));
100 FilePath final_path(storage_path());
101 final_path = final_path.Append("test.profile");
102 scoped_ptr<KeyFileStore> storage(new KeyFileStore(glib));
103 storage->set_path(final_path);
104 if (!storage->Open())
105 return NULL;
106 profile->set_storage(storage.release()); // Passes ownership.
107 return profile.release();
108 }
109
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700110 bool CreateBackingStoreForService(ScopedTempDir *temp_dir,
111 const string &profile_identifier,
112 const string &service_name) {
113 GLib glib;
114 KeyFileStore store(&glib);
115 store.set_path(temp_dir->path().Append(profile_identifier + ".profile"));
116 return store.Open() &&
117 store.SetString(service_name, "rather", "irrelevant") &&
118 store.Close();
119 }
120
121 Error::Type TestCreateProfile(Manager *manager, const string &name) {
122 Error error;
123 manager->CreateProfile(name, &error);
124 return error.type();
125 }
126
127 Error::Type TestPopAnyProfile(Manager *manager) {
128 Error error;
129 manager->PopAnyProfile(&error);
130 return error.type();
131 }
132
133 Error::Type TestPopProfile(Manager *manager, const string &name) {
134 Error error;
135 manager->PopProfile(name, &error);
136 return error.type();
137 }
138
139 Error::Type TestPushProfile(Manager *manager, const string &name) {
140 Error error;
141 manager->PushProfile(name, &error);
142 return error.type();
143 }
Paul Stewartf1ce5d22011-05-19 13:10:20 -0700144 protected:
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700145 scoped_refptr<MockWiFi> mock_wifi_;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700146 vector<scoped_refptr<MockDevice> > mock_devices_;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700147};
148
Paul Stewart22aa71b2011-09-16 12:15:11 -0700149bool ManagerTest::ServiceOrderIs(ServiceRefPtr svc0, ServiceRefPtr svc1) {
150 return (svc0.get() == manager()->services_[0].get() &&
151 svc1.get() == manager()->services_[1].get());
152}
153
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700154TEST_F(ManagerTest, Contains) {
mukesh agrawalde29fa82011-09-16 16:16:36 -0700155 EXPECT_TRUE(manager()->store().Contains(flimflam::kStateProperty));
156 EXPECT_FALSE(manager()->store().Contains(""));
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700157}
158
Chris Masone9be4a9d2011-05-16 15:44:09 -0700159TEST_F(ManagerTest, DeviceRegistration) {
Paul Stewart22aa71b2011-09-16 12:15:11 -0700160 ON_CALL(*mock_devices_[0].get(), TechnologyIs(Technology::kEthernet))
Chris Masone3c3f6a12011-07-01 10:01:41 -0700161 .WillByDefault(Return(true));
Paul Stewart22aa71b2011-09-16 12:15:11 -0700162 ON_CALL(*mock_devices_[1].get(), TechnologyIs(Technology::kWifi))
Chris Masone9be4a9d2011-05-16 15:44:09 -0700163 .WillByDefault(Return(true));
Paul Stewart22aa71b2011-09-16 12:15:11 -0700164 ON_CALL(*mock_devices_[2].get(), TechnologyIs(Technology::kCellular))
Darin Petkov6f9eaa32011-08-09 15:26:44 -0700165 .WillByDefault(Return(true));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700166
Paul Stewart22aa71b2011-09-16 12:15:11 -0700167 manager()->RegisterDevice(mock_devices_[0]);
168 manager()->RegisterDevice(mock_devices_[1]);
169 manager()->RegisterDevice(mock_devices_[2]);
Chris Masone9be4a9d2011-05-16 15:44:09 -0700170
Paul Stewart22aa71b2011-09-16 12:15:11 -0700171 EXPECT_TRUE(IsDeviceRegistered(mock_devices_[0], Technology::kEthernet));
172 EXPECT_TRUE(IsDeviceRegistered(mock_devices_[1], Technology::kWifi));
173 EXPECT_TRUE(IsDeviceRegistered(mock_devices_[2], Technology::kCellular));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700174}
175
176TEST_F(ManagerTest, DeviceDeregistration) {
Paul Stewart22aa71b2011-09-16 12:15:11 -0700177 ON_CALL(*mock_devices_[0].get(), TechnologyIs(Technology::kEthernet))
Chris Masone3c3f6a12011-07-01 10:01:41 -0700178 .WillByDefault(Return(true));
Paul Stewart22aa71b2011-09-16 12:15:11 -0700179 ON_CALL(*mock_devices_[1].get(), TechnologyIs(Technology::kWifi))
Chris Masone9be4a9d2011-05-16 15:44:09 -0700180 .WillByDefault(Return(true));
181
Paul Stewart22aa71b2011-09-16 12:15:11 -0700182 manager()->RegisterDevice(mock_devices_[0].get());
183 manager()->RegisterDevice(mock_devices_[1].get());
Chris Masone9be4a9d2011-05-16 15:44:09 -0700184
Paul Stewart22aa71b2011-09-16 12:15:11 -0700185 ASSERT_TRUE(IsDeviceRegistered(mock_devices_[0], Technology::kEthernet));
186 ASSERT_TRUE(IsDeviceRegistered(mock_devices_[1], Technology::kWifi));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700187
Paul Stewart22aa71b2011-09-16 12:15:11 -0700188 EXPECT_CALL(*mock_devices_[0].get(), Stop());
189 manager()->DeregisterDevice(mock_devices_[0].get());
190 EXPECT_FALSE(IsDeviceRegistered(mock_devices_[0], Technology::kEthernet));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700191
Paul Stewart22aa71b2011-09-16 12:15:11 -0700192 EXPECT_CALL(*mock_devices_[1].get(), Stop());
193 manager()->DeregisterDevice(mock_devices_[1].get());
194 EXPECT_FALSE(IsDeviceRegistered(mock_devices_[1], Technology::kWifi));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700195}
196
197TEST_F(ManagerTest, ServiceRegistration) {
Chris Masone9d779932011-08-25 16:33:41 -0700198 // It's much easier and safer to use a real GLib for this test.
199 GLib glib;
Chris Masone2176a882011-09-14 22:29:15 -0700200 Manager manager(control_interface(),
201 dispatcher(),
Chris Masone9d779932011-08-25 16:33:41 -0700202 &glib,
203 run_path(),
204 storage_path(),
205 string());
Chris Masone6515aab2011-10-12 16:19:09 -0700206 ProfileRefPtr profile(CreateProfileForManager(&manager, &glib));
207 ASSERT_TRUE(profile.get());
Paul Stewarta849a3d2011-11-03 05:54:09 -0700208 AdoptProfile(&manager, profile);
Chris Masone6515aab2011-10-12 16:19:09 -0700209
Chris Masone9be4a9d2011-05-16 15:44:09 -0700210 scoped_refptr<MockService> mock_service(
Chris Masone2176a882011-09-14 22:29:15 -0700211 new NiceMock<MockService>(control_interface(),
212 dispatcher(),
Chris Masone9d779932011-08-25 16:33:41 -0700213 &manager));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700214 scoped_refptr<MockService> mock_service2(
Chris Masone2176a882011-09-14 22:29:15 -0700215 new NiceMock<MockService>(control_interface(),
216 dispatcher(),
Chris Masone9d779932011-08-25 16:33:41 -0700217 &manager));
mukesh agrawal51a7e932011-07-27 16:18:26 -0700218 string service1_name(mock_service->UniqueName());
219 string service2_name(mock_service2->UniqueName());
220
221 EXPECT_CALL(*mock_service.get(), GetRpcIdentifier())
222 .WillRepeatedly(Return(service1_name));
Chris Masone6791a432011-07-12 13:23:19 -0700223 EXPECT_CALL(*mock_service2.get(), GetRpcIdentifier())
mukesh agrawal51a7e932011-07-27 16:18:26 -0700224 .WillRepeatedly(Return(service2_name));
mukesh agrawal32399322011-09-01 10:53:43 -0700225 // TODO(quiche): make this EXPECT_CALL work (crosbug.com/20154)
Chris Masone9d779932011-08-25 16:33:41 -0700226 // EXPECT_CALL(*dynamic_cast<ManagerMockAdaptor *>(manager.adaptor_.get()),
mukesh agrawal32399322011-09-01 10:53:43 -0700227 // EmitRpcIdentifierArrayChanged(flimflam::kServicesProperty, _));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700228
Chris Masone9d779932011-08-25 16:33:41 -0700229 manager.RegisterService(mock_service);
230 manager.RegisterService(mock_service2);
Chris Masone9be4a9d2011-05-16 15:44:09 -0700231
Chris Masone9d779932011-08-25 16:33:41 -0700232 vector<string> rpc_ids = manager.EnumerateAvailableServices();
Chris Masone6791a432011-07-12 13:23:19 -0700233 set<string> ids(rpc_ids.begin(), rpc_ids.end());
mukesh agrawal51a7e932011-07-27 16:18:26 -0700234 EXPECT_EQ(2, ids.size());
235 EXPECT_TRUE(ContainsKey(ids, mock_service->GetRpcIdentifier()));
236 EXPECT_TRUE(ContainsKey(ids, mock_service2->GetRpcIdentifier()));
Chris Masone6791a432011-07-12 13:23:19 -0700237
Chris Masone9d779932011-08-25 16:33:41 -0700238 EXPECT_TRUE(manager.FindService(service1_name).get() != NULL);
239 EXPECT_TRUE(manager.FindService(service2_name).get() != NULL);
240
241 manager.Stop();
Chris Masone9be4a9d2011-05-16 15:44:09 -0700242}
243
Chris Masone6515aab2011-10-12 16:19:09 -0700244TEST_F(ManagerTest, RegisterKnownService) {
245 // It's much easier and safer to use a real GLib for this test.
246 GLib glib;
247 Manager manager(control_interface(),
248 dispatcher(),
249 &glib,
250 run_path(),
251 storage_path(),
252 string());
253 ProfileRefPtr profile(CreateProfileForManager(&manager, &glib));
254 ASSERT_TRUE(profile.get());
Paul Stewarta849a3d2011-11-03 05:54:09 -0700255 AdoptProfile(&manager, profile);
Chris Masone6515aab2011-10-12 16:19:09 -0700256 {
257 ServiceRefPtr service1(new ServiceUnderTest(control_interface(),
258 dispatcher(),
259 &manager));
260 service1->set_favorite(!service1->favorite());
261 ASSERT_TRUE(profile->AdoptService(service1));
262 ASSERT_TRUE(profile->ContainsService(service1));
263 } // Force destruction of service1.
264
265 ServiceRefPtr service2(new ServiceUnderTest(control_interface(),
266 dispatcher(),
267 &manager));
268 manager.RegisterService(service2);
269 EXPECT_EQ(service2->profile().get(), profile.get());
270 manager.Stop();
271}
272
273TEST_F(ManagerTest, RegisterUnknownService) {
274 // It's much easier and safer to use a real GLib for this test.
275 GLib glib;
276 Manager manager(control_interface(),
277 dispatcher(),
278 &glib,
279 run_path(),
280 storage_path(),
281 string());
282 ProfileRefPtr profile(CreateProfileForManager(&manager, &glib));
283 ASSERT_TRUE(profile.get());
Paul Stewarta849a3d2011-11-03 05:54:09 -0700284 AdoptProfile(&manager, profile);
Chris Masone6515aab2011-10-12 16:19:09 -0700285 {
286 ServiceRefPtr service1(new ServiceUnderTest(control_interface(),
287 dispatcher(),
288 &manager));
289 service1->set_favorite(!service1->favorite());
290 ASSERT_TRUE(profile->AdoptService(service1));
291 ASSERT_TRUE(profile->ContainsService(service1));
292 } // Force destruction of service1.
293 scoped_refptr<MockService> mock_service2(
294 new NiceMock<MockService>(control_interface(),
295 dispatcher(),
296 &manager));
297 EXPECT_CALL(*mock_service2.get(), GetStorageIdentifier())
298 .WillRepeatedly(Return(mock_service2->UniqueName()));
299 manager.RegisterService(mock_service2);
300 EXPECT_NE(mock_service2->profile().get(), profile.get());
301 manager.Stop();
302}
303
Chris Masonea8a2c252011-06-27 22:16:30 -0700304TEST_F(ManagerTest, GetProperties) {
Chris Masoneb9c00592011-10-06 13:10:39 -0700305 ProfileRefPtr profile(new MockProfile(control_interface(), manager(), ""));
Paul Stewarta849a3d2011-11-03 05:54:09 -0700306 AdoptProfile(manager(), profile);
Chris Masonea8a2c252011-06-27 22:16:30 -0700307 map<string, ::DBus::Variant> props;
308 Error error(Error::kInvalidProperty, "");
309 {
310 ::DBus::Error dbus_error;
311 string expected("portal_list");
mukesh agrawalde29fa82011-09-16 16:16:36 -0700312 manager()->mutable_store()->SetStringProperty(
313 flimflam::kCheckPortalListProperty,
314 expected,
315 &error);
Chris Masone9d779932011-08-25 16:33:41 -0700316 DBusAdaptor::GetProperties(manager()->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700317 ASSERT_FALSE(props.find(flimflam::kCheckPortalListProperty) == props.end());
318 EXPECT_EQ(props[flimflam::kCheckPortalListProperty].reader().get_string(),
319 expected);
320 }
321 {
322 ::DBus::Error dbus_error;
323 bool expected = true;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700324 manager()->mutable_store()->SetBoolProperty(flimflam::kOfflineModeProperty,
325 expected,
326 &error);
Chris Masone9d779932011-08-25 16:33:41 -0700327 DBusAdaptor::GetProperties(manager()->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700328 ASSERT_FALSE(props.find(flimflam::kOfflineModeProperty) == props.end());
329 EXPECT_EQ(props[flimflam::kOfflineModeProperty].reader().get_bool(),
330 expected);
331 }
332}
333
Chris Masone3c3f6a12011-07-01 10:01:41 -0700334TEST_F(ManagerTest, GetDevicesProperty) {
Chris Masoneb9c00592011-10-06 13:10:39 -0700335 ProfileRefPtr profile(new MockProfile(control_interface(), manager(), ""));
Paul Stewarta849a3d2011-11-03 05:54:09 -0700336 AdoptProfile(manager(), profile);
Paul Stewart22aa71b2011-09-16 12:15:11 -0700337 manager()->RegisterDevice(mock_devices_[0].get());
338 manager()->RegisterDevice(mock_devices_[1].get());
Chris Masone3c3f6a12011-07-01 10:01:41 -0700339 {
340 map<string, ::DBus::Variant> props;
341 ::DBus::Error dbus_error;
Chris Masone9d779932011-08-25 16:33:41 -0700342 DBusAdaptor::GetProperties(manager()->store(), &props, &dbus_error);
Chris Masone3c3f6a12011-07-01 10:01:41 -0700343 ASSERT_FALSE(props.find(flimflam::kDevicesProperty) == props.end());
344 Strings devices =
345 props[flimflam::kDevicesProperty].operator vector<string>();
346 EXPECT_EQ(2, devices.size());
347 }
Chris Masone3c3f6a12011-07-01 10:01:41 -0700348}
349
Chris Masone6791a432011-07-12 13:23:19 -0700350TEST_F(ManagerTest, MoveService) {
Chris Masone2176a882011-09-14 22:29:15 -0700351 Manager manager(control_interface(),
352 dispatcher(),
Chris Masone6515aab2011-10-12 16:19:09 -0700353 glib(),
Chris Masone9d779932011-08-25 16:33:41 -0700354 run_path(),
355 storage_path(),
356 string());
Chris Masone6515aab2011-10-12 16:19:09 -0700357 scoped_refptr<MockService> s2(new MockService(control_interface(),
358 dispatcher(),
359 &manager));
360 // Inject an actual profile, backed by a fake StoreInterface
Chris Masoneb9c00592011-10-06 13:10:39 -0700361 {
Chris Masone6515aab2011-10-12 16:19:09 -0700362 Profile::Identifier id("irrelevant");
Chris Masoneb9c00592011-10-06 13:10:39 -0700363 ProfileRefPtr profile(
364 new Profile(control_interface(), &manager, id, "", false));
365 MockStore *storage = new MockStore;
Chris Masone6515aab2011-10-12 16:19:09 -0700366 // Say we don't have |s2| the first time asked, then that we do.
367 EXPECT_CALL(*storage, ContainsGroup(s2->GetStorageIdentifier()))
368 .WillOnce(Return(false))
369 .WillRepeatedly(Return(true));
370 EXPECT_CALL(*storage, Flush())
371 .Times(AnyNumber())
372 .WillRepeatedly(Return(true));
Chris Masoneb9c00592011-10-06 13:10:39 -0700373 profile->set_storage(storage);
Paul Stewarta849a3d2011-11-03 05:54:09 -0700374 AdoptProfile(&manager, profile);
Chris Masoneb9c00592011-10-06 13:10:39 -0700375 }
Chris Masone6515aab2011-10-12 16:19:09 -0700376 // Create a profile that already has |s2| in it.
377 ProfileRefPtr profile(new EphemeralProfile(control_interface(), &manager));
378 profile->AdoptService(s2);
Chris Masone9d779932011-08-25 16:33:41 -0700379
Chris Masone6515aab2011-10-12 16:19:09 -0700380 // Now, move the Service |s2| to another profile.
381 EXPECT_CALL(*s2.get(), Save(_)).WillOnce(Return(true));
382 ASSERT_TRUE(manager.MoveServiceToProfile(s2, manager.ActiveProfile()));
Chris Masone6791a432011-07-12 13:23:19 -0700383
384 // Force destruction of the original Profile, to ensure that the Service
385 // is kept alive and populated with data.
386 profile = NULL;
Chris Masone6515aab2011-10-12 16:19:09 -0700387 ASSERT_TRUE(manager.ActiveProfile()->ContainsService(s2));
Chris Masone9d779932011-08-25 16:33:41 -0700388 manager.Stop();
Chris Masone6791a432011-07-12 13:23:19 -0700389}
390
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700391TEST_F(ManagerTest, CreateProfile) {
392 // It's much easier to use real Glib here since we want the storage
393 // side-effects.
394 GLib glib;
395 ScopedTempDir temp_dir;
396 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
397
398 Manager manager(control_interface(),
399 dispatcher(),
400 &glib,
401 run_path(),
402 storage_path(),
403 temp_dir.path().value());
404
405 // Invalid name should be rejected.
406 EXPECT_EQ(Error::kInvalidArguments, TestCreateProfile(&manager, ""));
407
408 // Valid name is still rejected because we can't create a profile
409 // that doesn't have a user component. Such profile names are
410 // reserved for the single DefaultProfile the manager creates
411 // at startup.
412 EXPECT_EQ(Error::kInvalidArguments, TestCreateProfile(&manager, "valid"));
413
414 // We should succeed in creating a valid user profile.
415 const char kProfile[] = "~user/profile";
416 EXPECT_EQ(Error::kSuccess, TestCreateProfile(&manager, kProfile));
417
418 // We should fail in creating it a second time (already exists).
419 EXPECT_EQ(Error::kAlreadyExists, TestCreateProfile(&manager, kProfile));
420}
421
422TEST_F(ManagerTest, PushPopProfile) {
423 // It's much easier to use real Glib in creating a Manager for this
424 // test here since we want the storage side-effects.
425 GLib glib;
426 ScopedTempDir temp_dir;
427 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
428 Manager manager(control_interface(),
429 dispatcher(),
430 &glib,
431 run_path(),
432 storage_path(),
433 temp_dir.path().value());
434
435 // Pushing an invalid profile should fail.
436 EXPECT_EQ(Error::kInvalidArguments, TestPushProfile(&manager, ""));
437
438 // Pushing a default profile name should fail.
439 EXPECT_EQ(Error::kInvalidArguments, TestPushProfile(&manager, "default"));
440
441 const char kProfile0[] = "~user/profile0";
442 const char kProfile1[] = "~user/profile1";
443
444 // Create a couple of profiles.
445 ASSERT_EQ(Error::kSuccess, TestCreateProfile(&manager, kProfile0));
446 ASSERT_EQ(Error::kSuccess, TestCreateProfile(&manager, kProfile1));
447
448 // Push these profiles on the stack.
449 EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager, kProfile0));
450 EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager, kProfile1));
451
452 // Pushing a profile a second time should fail.
453 EXPECT_EQ(Error::kAlreadyExists, TestPushProfile(&manager, kProfile0));
454 EXPECT_EQ(Error::kAlreadyExists, TestPushProfile(&manager, kProfile1));
455
456 // Active profile should be the last one we pushed.
457 EXPECT_EQ(kProfile1, "~" + manager.GetActiveProfileName());
458
459 // Make sure a profile name that doesn't exist fails.
460 const char kProfile2Id[] = "profile2";
461 const string kProfile2 = base::StringPrintf("~user/%s", kProfile2Id);
462 EXPECT_EQ(Error::kNotFound, TestPushProfile(&manager, kProfile2));
463
464 // Create a new service, with a specific storage name.
465 scoped_refptr<MockService> service(
466 new NiceMock<MockService>(control_interface(),
467 dispatcher(),
468 &manager));
469 const char kServiceName[] = "service_storage_name";
470 EXPECT_CALL(*service.get(), GetStorageIdentifier())
471 .WillRepeatedly(Return(kServiceName));
472 EXPECT_CALL(*service.get(), Load(_))
473 .WillRepeatedly(Return(true));
474
475 // Add this service to the manager -- it should end up in the ephemeral
476 // profile.
477 manager.RegisterService(service);
478 ASSERT_EQ(manager.ephemeral_profile_, service->profile());
479
480 // Create storage for a profile that contains the service storage name.
481 ASSERT_TRUE(CreateBackingStoreForService(&temp_dir, kProfile2Id,
482 kServiceName));
483
484 // When we push the profile, the service should move away from the
485 // ephemeral profile to this new profile since it has an entry for
486 // this service.
487 EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager, kProfile2));
488 EXPECT_NE(manager.ephemeral_profile_, service->profile());
489 EXPECT_EQ(kProfile2, "~" + service->profile()->GetFriendlyName());
490
491 // Insert another profile that should supersede ownership of the service.
492 const char kProfile3Id[] = "profile3";
493 const string kProfile3 = base::StringPrintf("~user/%s", kProfile3Id);
494 ASSERT_TRUE(CreateBackingStoreForService(&temp_dir, kProfile3Id,
495 kServiceName));
496 EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager, kProfile3));
497 EXPECT_EQ(kProfile3, "~" + service->profile()->GetFriendlyName());
498
499 // Popping an invalid profile name should fail.
500 EXPECT_EQ(Error::kInvalidArguments, TestPopProfile(&manager, "~"));
501
502 // Popping an profile that is not at the top of the stack should fail.
503 EXPECT_EQ(Error::kNotSupported, TestPopProfile(&manager, kProfile0));
504
505 // Popping the top profile should succeed.
506 EXPECT_EQ(Error::kSuccess, TestPopProfile(&manager, kProfile3));
507
508 // Moreover the service should have switched profiles to profile 2.
509 EXPECT_EQ(kProfile2, "~" + service->profile()->GetFriendlyName());
510
511 // Popping the top profile should succeed.
512 EXPECT_EQ(Error::kSuccess, TestPopAnyProfile(&manager));
513
514 // The service should now revert to the ephemeral profile.
515 EXPECT_EQ(manager.ephemeral_profile_, service->profile());
516
517 // Pop the remaining two services off the stack.
518 EXPECT_EQ(Error::kSuccess, TestPopAnyProfile(&manager));
519 EXPECT_EQ(Error::kSuccess, TestPopAnyProfile(&manager));
520
521 // Next pop should fail with "stack is empty".
522 EXPECT_EQ(Error::kNotFound, TestPopAnyProfile(&manager));
523}
524
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700525TEST_F(ManagerTest, Dispatch) {
Chris Masonea8a2c252011-06-27 22:16:30 -0700526 {
527 ::DBus::Error error;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700528 EXPECT_TRUE(DBusAdaptor::DispatchOnType(manager()->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -0700529 flimflam::kOfflineModeProperty,
530 PropertyStoreTest::kBoolV,
531 &error));
532 }
533 {
534 ::DBus::Error error;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700535 EXPECT_TRUE(DBusAdaptor::DispatchOnType(manager()->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -0700536 flimflam::kCountryProperty,
537 PropertyStoreTest::kStringV,
538 &error));
539 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700540 // Attempt to write with value of wrong type should return InvalidArgs.
Chris Masonea8a2c252011-06-27 22:16:30 -0700541 {
542 ::DBus::Error error;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700543 EXPECT_FALSE(DBusAdaptor::DispatchOnType(manager()->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -0700544 flimflam::kCountryProperty,
545 PropertyStoreTest::kBoolV,
546 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700547 EXPECT_EQ(invalid_args(), error.name());
Chris Masonea8a2c252011-06-27 22:16:30 -0700548 }
549 {
550 ::DBus::Error error;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700551 EXPECT_FALSE(DBusAdaptor::DispatchOnType(manager()->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -0700552 flimflam::kOfflineModeProperty,
553 PropertyStoreTest::kStringV,
554 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700555 EXPECT_EQ(invalid_args(), error.name());
Chris Masonea8a2c252011-06-27 22:16:30 -0700556 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700557 // Attempt to write R/O property should return InvalidArgs.
Chris Masonea8a2c252011-06-27 22:16:30 -0700558 {
559 ::DBus::Error error;
560 EXPECT_FALSE(DBusAdaptor::DispatchOnType(
mukesh agrawalde29fa82011-09-16 16:16:36 -0700561 manager()->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -0700562 flimflam::kEnabledTechnologiesProperty,
563 PropertyStoreTest::kStringsV,
564 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700565 EXPECT_EQ(invalid_args(), error.name());
Chris Masonea8a2c252011-06-27 22:16:30 -0700566 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700567}
568
mukesh agrawal32399322011-09-01 10:53:43 -0700569TEST_F(ManagerTest, RequestScan) {
570 {
571 Error error;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700572 manager()->RegisterDevice(mock_devices_[0].get());
573 manager()->RegisterDevice(mock_devices_[1].get());
574 EXPECT_CALL(*mock_devices_[0], TechnologyIs(Technology::kWifi))
mukesh agrawal32399322011-09-01 10:53:43 -0700575 .WillRepeatedly(Return(true));
Paul Stewart22aa71b2011-09-16 12:15:11 -0700576 EXPECT_CALL(*mock_devices_[0], Scan(_));
577 EXPECT_CALL(*mock_devices_[1], TechnologyIs(Technology::kWifi))
mukesh agrawal32399322011-09-01 10:53:43 -0700578 .WillRepeatedly(Return(false));
Paul Stewart22aa71b2011-09-16 12:15:11 -0700579 EXPECT_CALL(*mock_devices_[1], Scan(_)).Times(0);
Chris Masone9d779932011-08-25 16:33:41 -0700580 manager()->RequestScan(flimflam::kTypeWifi, &error);
mukesh agrawal32399322011-09-01 10:53:43 -0700581 }
582
583 {
584 Error error;
Chris Masone9d779932011-08-25 16:33:41 -0700585 manager()->RequestScan("bogus_device_type", &error);
mukesh agrawal32399322011-09-01 10:53:43 -0700586 EXPECT_EQ(Error::kInvalidArguments, error.type());
587 }
588}
589
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700590TEST_F(ManagerTest, GetWifiServiceNoDevice) {
591 KeyValueStore args;
592 Error e;
593 manager()->GetWifiService(args, &e);
594 EXPECT_EQ(Error::kInvalidArguments, e.type());
595 EXPECT_EQ("no wifi devices available", e.message());
596}
597
598TEST_F(ManagerTest, GetWifiService) {
599 KeyValueStore args;
600 Error e;
601 WiFiServiceRefPtr wifi_service;
602
603 manager()->RegisterDevice(mock_wifi_);
604 EXPECT_CALL(*mock_wifi_, GetService(_, _))
605 .WillRepeatedly(Return(wifi_service));
606 manager()->GetWifiService(args, &e);
607}
608
Paul Stewart22aa71b2011-09-16 12:15:11 -0700609TEST_F(ManagerTest, TechnologyOrder) {
610 Error error;
611 manager()->SetTechnologyOrder(string(flimflam::kTypeEthernet) + "," +
612 string(flimflam::kTypeWifi), &error);
613 ASSERT_TRUE(error.IsSuccess());
614 EXPECT_EQ(manager()->GetTechnologyOrder(),
615 string(flimflam::kTypeEthernet) + "," +
616 string(flimflam::kTypeWifi));
617
618 manager()->SetTechnologyOrder(string(flimflam::kTypeEthernet) + "x," +
619 string(flimflam::kTypeWifi), &error);
620 ASSERT_FALSE(error.IsSuccess());
621 EXPECT_EQ(Error::kInvalidArguments, error.type());
622 EXPECT_EQ(string(flimflam::kTypeEthernet) + "," +
623 string(flimflam::kTypeWifi),
624 manager()->GetTechnologyOrder());
625}
626
627TEST_F(ManagerTest, SortServices) {
628 scoped_refptr<MockService> mock_service0(
629 new NiceMock<MockService>(control_interface(),
630 dispatcher(),
631 manager()));
632 scoped_refptr<MockService> mock_service1(
633 new NiceMock<MockService>(control_interface(),
634 dispatcher(),
635 manager()));
636 string service1_name(mock_service0->UniqueName());
637 string service2_name(mock_service1->UniqueName());
638
639 manager()->RegisterService(mock_service0);
640 manager()->RegisterService(mock_service1);
641
642 // Services should already be sorted by UniqueName
643 EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
644
645 // Asking explictly to sort services should not change anything
646 manager()->SortServices();
647 EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
648
649 // Two otherwise equal services should be reordered by strength
650 mock_service1->set_strength(1);
651 manager()->UpdateService(mock_service1);
652 EXPECT_TRUE(ServiceOrderIs(mock_service1, mock_service0));
653
654 // Security
Paul Stewart1ca3e852011-11-04 07:50:49 -0700655 mock_service0->set_security_level(1);
Paul Stewart22aa71b2011-09-16 12:15:11 -0700656 manager()->UpdateService(mock_service0);
657 EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
658
659 // Technology
660 EXPECT_CALL(*mock_service0.get(), TechnologyIs(Technology::kWifi))
661 .WillRepeatedly(Return(true));
662 EXPECT_CALL(*mock_service1.get(), TechnologyIs(Technology::kEthernet))
663 .WillRepeatedly(Return(true));
664 // NB: Redefine default (false) return values so we don't use the default rule
665 // which makes the logs noisier
666 EXPECT_CALL(*mock_service0.get(), TechnologyIs(Ne(Technology::kWifi)))
667 .WillRepeatedly(Return(false));
668 EXPECT_CALL(*mock_service1.get(), TechnologyIs(Ne(Technology::kEthernet)))
669 .WillRepeatedly(Return(false));
670
671 Error error;
672 manager()->SetTechnologyOrder(string(flimflam::kTypeEthernet) + "," +
673 string(flimflam::kTypeWifi), &error);
674 EXPECT_TRUE(error.IsSuccess());
675 EXPECT_TRUE(ServiceOrderIs(mock_service1, mock_service0));
676
677 manager()->SetTechnologyOrder(string(flimflam::kTypeWifi) + "," +
678 string(flimflam::kTypeEthernet), &error);
679 EXPECT_TRUE(error.IsSuccess());
680 EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
681
682 // Priority
683 mock_service0->set_priority(1);
684 manager()->UpdateService(mock_service0);
685 EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
686
687 // Favorite
688 mock_service1->set_favorite(true);
689 manager()->UpdateService(mock_service1);
690 EXPECT_TRUE(ServiceOrderIs(mock_service1, mock_service0));
691
692 // Connecting
693 EXPECT_CALL(*mock_service0.get(), state())
694 .WillRepeatedly(Return(Service::kStateAssociating));
695 manager()->UpdateService(mock_service0);
696 EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
697
698 // Connected
699 EXPECT_CALL(*mock_service1.get(), state())
700 .WillRepeatedly(Return(Service::kStateConnected));
701 manager()->UpdateService(mock_service1);
702 EXPECT_TRUE(ServiceOrderIs(mock_service1, mock_service0));
703
704 manager()->DeregisterService(mock_service0);
705 manager()->DeregisterService(mock_service1);
706}
707
Thieu Le1271d682011-11-02 22:48:19 +0000708TEST_F(ManagerTest, DisconnectServicesOnStop) {
709 scoped_refptr<MockService> mock_service(
710 new NiceMock<MockService>(control_interface(),
711 dispatcher(),
712 manager()));
713 manager()->RegisterService(mock_service);
714 EXPECT_CALL(*mock_service.get(), Disconnect()).Times(1);
715 manager()->Stop();
716}
717
Chris Masone9be4a9d2011-05-16 15:44:09 -0700718} // namespace shill