blob: 713360f19c28fd3fe261ace882a3824b451a63b9 [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
Chris Masone6515aab2011-10-12 16:19:09 -070089 Profile *CreateProfileForManager(Manager *manager, GLib *glib) {
90 Profile::Identifier id("rather", "irrelevant");
91 scoped_ptr<Profile> profile(new Profile(control_interface(),
92 manager,
93 id,
94 "",
95 false));
96 FilePath final_path(storage_path());
97 final_path = final_path.Append("test.profile");
98 scoped_ptr<KeyFileStore> storage(new KeyFileStore(glib));
99 storage->set_path(final_path);
100 if (!storage->Open())
101 return NULL;
102 profile->set_storage(storage.release()); // Passes ownership.
103 return profile.release();
104 }
105
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700106 bool CreateBackingStoreForService(ScopedTempDir *temp_dir,
107 const string &profile_identifier,
108 const string &service_name) {
109 GLib glib;
110 KeyFileStore store(&glib);
111 store.set_path(temp_dir->path().Append(profile_identifier + ".profile"));
112 return store.Open() &&
113 store.SetString(service_name, "rather", "irrelevant") &&
114 store.Close();
115 }
116
117 Error::Type TestCreateProfile(Manager *manager, const string &name) {
118 Error error;
119 manager->CreateProfile(name, &error);
120 return error.type();
121 }
122
123 Error::Type TestPopAnyProfile(Manager *manager) {
124 Error error;
125 manager->PopAnyProfile(&error);
126 return error.type();
127 }
128
129 Error::Type TestPopProfile(Manager *manager, const string &name) {
130 Error error;
131 manager->PopProfile(name, &error);
132 return error.type();
133 }
134
135 Error::Type TestPushProfile(Manager *manager, const string &name) {
136 Error error;
137 manager->PushProfile(name, &error);
138 return error.type();
139 }
Paul Stewartf1ce5d22011-05-19 13:10:20 -0700140 protected:
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700141 scoped_refptr<MockWiFi> mock_wifi_;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700142 vector<scoped_refptr<MockDevice> > mock_devices_;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700143};
144
Paul Stewart22aa71b2011-09-16 12:15:11 -0700145bool ManagerTest::ServiceOrderIs(ServiceRefPtr svc0, ServiceRefPtr svc1) {
146 return (svc0.get() == manager()->services_[0].get() &&
147 svc1.get() == manager()->services_[1].get());
148}
149
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700150TEST_F(ManagerTest, Contains) {
mukesh agrawalde29fa82011-09-16 16:16:36 -0700151 EXPECT_TRUE(manager()->store().Contains(flimflam::kStateProperty));
152 EXPECT_FALSE(manager()->store().Contains(""));
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700153}
154
Chris Masone9be4a9d2011-05-16 15:44:09 -0700155TEST_F(ManagerTest, DeviceRegistration) {
Paul Stewart22aa71b2011-09-16 12:15:11 -0700156 ON_CALL(*mock_devices_[0].get(), TechnologyIs(Technology::kEthernet))
Chris Masone3c3f6a12011-07-01 10:01:41 -0700157 .WillByDefault(Return(true));
Paul Stewart22aa71b2011-09-16 12:15:11 -0700158 ON_CALL(*mock_devices_[1].get(), TechnologyIs(Technology::kWifi))
Chris Masone9be4a9d2011-05-16 15:44:09 -0700159 .WillByDefault(Return(true));
Paul Stewart22aa71b2011-09-16 12:15:11 -0700160 ON_CALL(*mock_devices_[2].get(), TechnologyIs(Technology::kCellular))
Darin Petkov6f9eaa32011-08-09 15:26:44 -0700161 .WillByDefault(Return(true));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700162
Paul Stewart22aa71b2011-09-16 12:15:11 -0700163 manager()->RegisterDevice(mock_devices_[0]);
164 manager()->RegisterDevice(mock_devices_[1]);
165 manager()->RegisterDevice(mock_devices_[2]);
Chris Masone9be4a9d2011-05-16 15:44:09 -0700166
Paul Stewart22aa71b2011-09-16 12:15:11 -0700167 EXPECT_TRUE(IsDeviceRegistered(mock_devices_[0], Technology::kEthernet));
168 EXPECT_TRUE(IsDeviceRegistered(mock_devices_[1], Technology::kWifi));
169 EXPECT_TRUE(IsDeviceRegistered(mock_devices_[2], Technology::kCellular));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700170}
171
172TEST_F(ManagerTest, DeviceDeregistration) {
Paul Stewart22aa71b2011-09-16 12:15:11 -0700173 ON_CALL(*mock_devices_[0].get(), TechnologyIs(Technology::kEthernet))
Chris Masone3c3f6a12011-07-01 10:01:41 -0700174 .WillByDefault(Return(true));
Paul Stewart22aa71b2011-09-16 12:15:11 -0700175 ON_CALL(*mock_devices_[1].get(), TechnologyIs(Technology::kWifi))
Chris Masone9be4a9d2011-05-16 15:44:09 -0700176 .WillByDefault(Return(true));
177
Paul Stewart22aa71b2011-09-16 12:15:11 -0700178 manager()->RegisterDevice(mock_devices_[0].get());
179 manager()->RegisterDevice(mock_devices_[1].get());
Chris Masone9be4a9d2011-05-16 15:44:09 -0700180
Paul Stewart22aa71b2011-09-16 12:15:11 -0700181 ASSERT_TRUE(IsDeviceRegistered(mock_devices_[0], Technology::kEthernet));
182 ASSERT_TRUE(IsDeviceRegistered(mock_devices_[1], Technology::kWifi));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700183
Paul Stewart22aa71b2011-09-16 12:15:11 -0700184 EXPECT_CALL(*mock_devices_[0].get(), Stop());
185 manager()->DeregisterDevice(mock_devices_[0].get());
186 EXPECT_FALSE(IsDeviceRegistered(mock_devices_[0], Technology::kEthernet));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700187
Paul Stewart22aa71b2011-09-16 12:15:11 -0700188 EXPECT_CALL(*mock_devices_[1].get(), Stop());
189 manager()->DeregisterDevice(mock_devices_[1].get());
190 EXPECT_FALSE(IsDeviceRegistered(mock_devices_[1], Technology::kWifi));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700191}
192
193TEST_F(ManagerTest, ServiceRegistration) {
Chris Masone9d779932011-08-25 16:33:41 -0700194 // It's much easier and safer to use a real GLib for this test.
195 GLib glib;
Chris Masone2176a882011-09-14 22:29:15 -0700196 Manager manager(control_interface(),
197 dispatcher(),
Chris Masone9d779932011-08-25 16:33:41 -0700198 &glib,
199 run_path(),
200 storage_path(),
201 string());
Chris Masone6515aab2011-10-12 16:19:09 -0700202 ProfileRefPtr profile(CreateProfileForManager(&manager, &glib));
203 ASSERT_TRUE(profile.get());
204 manager.AdoptProfile(profile);
205
Chris Masone9be4a9d2011-05-16 15:44:09 -0700206 scoped_refptr<MockService> mock_service(
Chris Masone2176a882011-09-14 22:29:15 -0700207 new NiceMock<MockService>(control_interface(),
208 dispatcher(),
Chris Masone9d779932011-08-25 16:33:41 -0700209 &manager));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700210 scoped_refptr<MockService> mock_service2(
Chris Masone2176a882011-09-14 22:29:15 -0700211 new NiceMock<MockService>(control_interface(),
212 dispatcher(),
Chris Masone9d779932011-08-25 16:33:41 -0700213 &manager));
mukesh agrawal51a7e932011-07-27 16:18:26 -0700214 string service1_name(mock_service->UniqueName());
215 string service2_name(mock_service2->UniqueName());
216
217 EXPECT_CALL(*mock_service.get(), GetRpcIdentifier())
218 .WillRepeatedly(Return(service1_name));
Chris Masone6791a432011-07-12 13:23:19 -0700219 EXPECT_CALL(*mock_service2.get(), GetRpcIdentifier())
mukesh agrawal51a7e932011-07-27 16:18:26 -0700220 .WillRepeatedly(Return(service2_name));
mukesh agrawal32399322011-09-01 10:53:43 -0700221 // TODO(quiche): make this EXPECT_CALL work (crosbug.com/20154)
Chris Masone9d779932011-08-25 16:33:41 -0700222 // EXPECT_CALL(*dynamic_cast<ManagerMockAdaptor *>(manager.adaptor_.get()),
mukesh agrawal32399322011-09-01 10:53:43 -0700223 // EmitRpcIdentifierArrayChanged(flimflam::kServicesProperty, _));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700224
Chris Masone9d779932011-08-25 16:33:41 -0700225 manager.RegisterService(mock_service);
226 manager.RegisterService(mock_service2);
Chris Masone9be4a9d2011-05-16 15:44:09 -0700227
Chris Masone9d779932011-08-25 16:33:41 -0700228 vector<string> rpc_ids = manager.EnumerateAvailableServices();
Chris Masone6791a432011-07-12 13:23:19 -0700229 set<string> ids(rpc_ids.begin(), rpc_ids.end());
mukesh agrawal51a7e932011-07-27 16:18:26 -0700230 EXPECT_EQ(2, ids.size());
231 EXPECT_TRUE(ContainsKey(ids, mock_service->GetRpcIdentifier()));
232 EXPECT_TRUE(ContainsKey(ids, mock_service2->GetRpcIdentifier()));
Chris Masone6791a432011-07-12 13:23:19 -0700233
Chris Masone9d779932011-08-25 16:33:41 -0700234 EXPECT_TRUE(manager.FindService(service1_name).get() != NULL);
235 EXPECT_TRUE(manager.FindService(service2_name).get() != NULL);
236
237 manager.Stop();
Chris Masone9be4a9d2011-05-16 15:44:09 -0700238}
239
Chris Masone6515aab2011-10-12 16:19:09 -0700240TEST_F(ManagerTest, RegisterKnownService) {
241 // It's much easier and safer to use a real GLib for this test.
242 GLib glib;
243 Manager manager(control_interface(),
244 dispatcher(),
245 &glib,
246 run_path(),
247 storage_path(),
248 string());
249 ProfileRefPtr profile(CreateProfileForManager(&manager, &glib));
250 ASSERT_TRUE(profile.get());
251 manager.AdoptProfile(profile);
252 {
253 ServiceRefPtr service1(new ServiceUnderTest(control_interface(),
254 dispatcher(),
255 &manager));
256 service1->set_favorite(!service1->favorite());
257 ASSERT_TRUE(profile->AdoptService(service1));
258 ASSERT_TRUE(profile->ContainsService(service1));
259 } // Force destruction of service1.
260
261 ServiceRefPtr service2(new ServiceUnderTest(control_interface(),
262 dispatcher(),
263 &manager));
264 manager.RegisterService(service2);
265 EXPECT_EQ(service2->profile().get(), profile.get());
266 manager.Stop();
267}
268
269TEST_F(ManagerTest, RegisterUnknownService) {
270 // It's much easier and safer to use a real GLib for this test.
271 GLib glib;
272 Manager manager(control_interface(),
273 dispatcher(),
274 &glib,
275 run_path(),
276 storage_path(),
277 string());
278 ProfileRefPtr profile(CreateProfileForManager(&manager, &glib));
279 ASSERT_TRUE(profile.get());
280 manager.AdoptProfile(profile);
281 {
282 ServiceRefPtr service1(new ServiceUnderTest(control_interface(),
283 dispatcher(),
284 &manager));
285 service1->set_favorite(!service1->favorite());
286 ASSERT_TRUE(profile->AdoptService(service1));
287 ASSERT_TRUE(profile->ContainsService(service1));
288 } // Force destruction of service1.
289 scoped_refptr<MockService> mock_service2(
290 new NiceMock<MockService>(control_interface(),
291 dispatcher(),
292 &manager));
293 EXPECT_CALL(*mock_service2.get(), GetStorageIdentifier())
294 .WillRepeatedly(Return(mock_service2->UniqueName()));
295 manager.RegisterService(mock_service2);
296 EXPECT_NE(mock_service2->profile().get(), profile.get());
297 manager.Stop();
298}
299
Chris Masonea8a2c252011-06-27 22:16:30 -0700300TEST_F(ManagerTest, GetProperties) {
Chris Masoneb9c00592011-10-06 13:10:39 -0700301 ProfileRefPtr profile(new MockProfile(control_interface(), manager(), ""));
302 manager()->AdoptProfile(profile);
Chris Masonea8a2c252011-06-27 22:16:30 -0700303 map<string, ::DBus::Variant> props;
304 Error error(Error::kInvalidProperty, "");
305 {
306 ::DBus::Error dbus_error;
307 string expected("portal_list");
mukesh agrawalde29fa82011-09-16 16:16:36 -0700308 manager()->mutable_store()->SetStringProperty(
309 flimflam::kCheckPortalListProperty,
310 expected,
311 &error);
Chris Masone9d779932011-08-25 16:33:41 -0700312 DBusAdaptor::GetProperties(manager()->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700313 ASSERT_FALSE(props.find(flimflam::kCheckPortalListProperty) == props.end());
314 EXPECT_EQ(props[flimflam::kCheckPortalListProperty].reader().get_string(),
315 expected);
316 }
317 {
318 ::DBus::Error dbus_error;
319 bool expected = true;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700320 manager()->mutable_store()->SetBoolProperty(flimflam::kOfflineModeProperty,
321 expected,
322 &error);
Chris Masone9d779932011-08-25 16:33:41 -0700323 DBusAdaptor::GetProperties(manager()->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700324 ASSERT_FALSE(props.find(flimflam::kOfflineModeProperty) == props.end());
325 EXPECT_EQ(props[flimflam::kOfflineModeProperty].reader().get_bool(),
326 expected);
327 }
328}
329
Chris Masone3c3f6a12011-07-01 10:01:41 -0700330TEST_F(ManagerTest, GetDevicesProperty) {
Chris Masoneb9c00592011-10-06 13:10:39 -0700331 ProfileRefPtr profile(new MockProfile(control_interface(), manager(), ""));
332 manager()->AdoptProfile(profile);
Paul Stewart22aa71b2011-09-16 12:15:11 -0700333 manager()->RegisterDevice(mock_devices_[0].get());
334 manager()->RegisterDevice(mock_devices_[1].get());
Chris Masone3c3f6a12011-07-01 10:01:41 -0700335 {
336 map<string, ::DBus::Variant> props;
337 ::DBus::Error dbus_error;
Chris Masone9d779932011-08-25 16:33:41 -0700338 DBusAdaptor::GetProperties(manager()->store(), &props, &dbus_error);
Chris Masone3c3f6a12011-07-01 10:01:41 -0700339 ASSERT_FALSE(props.find(flimflam::kDevicesProperty) == props.end());
340 Strings devices =
341 props[flimflam::kDevicesProperty].operator vector<string>();
342 EXPECT_EQ(2, devices.size());
343 }
Chris Masone3c3f6a12011-07-01 10:01:41 -0700344}
345
Chris Masone6791a432011-07-12 13:23:19 -0700346TEST_F(ManagerTest, MoveService) {
Chris Masone2176a882011-09-14 22:29:15 -0700347 Manager manager(control_interface(),
348 dispatcher(),
Chris Masone6515aab2011-10-12 16:19:09 -0700349 glib(),
Chris Masone9d779932011-08-25 16:33:41 -0700350 run_path(),
351 storage_path(),
352 string());
Chris Masone6515aab2011-10-12 16:19:09 -0700353 scoped_refptr<MockService> s2(new MockService(control_interface(),
354 dispatcher(),
355 &manager));
356 // Inject an actual profile, backed by a fake StoreInterface
Chris Masoneb9c00592011-10-06 13:10:39 -0700357 {
Chris Masone6515aab2011-10-12 16:19:09 -0700358 Profile::Identifier id("irrelevant");
Chris Masoneb9c00592011-10-06 13:10:39 -0700359 ProfileRefPtr profile(
360 new Profile(control_interface(), &manager, id, "", false));
361 MockStore *storage = new MockStore;
Chris Masone6515aab2011-10-12 16:19:09 -0700362 // Say we don't have |s2| the first time asked, then that we do.
363 EXPECT_CALL(*storage, ContainsGroup(s2->GetStorageIdentifier()))
364 .WillOnce(Return(false))
365 .WillRepeatedly(Return(true));
366 EXPECT_CALL(*storage, Flush())
367 .Times(AnyNumber())
368 .WillRepeatedly(Return(true));
Chris Masoneb9c00592011-10-06 13:10:39 -0700369 profile->set_storage(storage);
370 manager.AdoptProfile(profile);
371 }
Chris Masone6515aab2011-10-12 16:19:09 -0700372 // Create a profile that already has |s2| in it.
373 ProfileRefPtr profile(new EphemeralProfile(control_interface(), &manager));
374 profile->AdoptService(s2);
Chris Masone9d779932011-08-25 16:33:41 -0700375
Chris Masone6515aab2011-10-12 16:19:09 -0700376 // Now, move the Service |s2| to another profile.
377 EXPECT_CALL(*s2.get(), Save(_)).WillOnce(Return(true));
378 ASSERT_TRUE(manager.MoveServiceToProfile(s2, manager.ActiveProfile()));
Chris Masone6791a432011-07-12 13:23:19 -0700379
380 // Force destruction of the original Profile, to ensure that the Service
381 // is kept alive and populated with data.
382 profile = NULL;
Chris Masone6515aab2011-10-12 16:19:09 -0700383 ASSERT_TRUE(manager.ActiveProfile()->ContainsService(s2));
Chris Masone9d779932011-08-25 16:33:41 -0700384 manager.Stop();
Chris Masone6791a432011-07-12 13:23:19 -0700385}
386
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700387TEST_F(ManagerTest, CreateProfile) {
388 // It's much easier to use real Glib here since we want the storage
389 // side-effects.
390 GLib glib;
391 ScopedTempDir temp_dir;
392 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
393
394 Manager manager(control_interface(),
395 dispatcher(),
396 &glib,
397 run_path(),
398 storage_path(),
399 temp_dir.path().value());
400
401 // Invalid name should be rejected.
402 EXPECT_EQ(Error::kInvalidArguments, TestCreateProfile(&manager, ""));
403
404 // Valid name is still rejected because we can't create a profile
405 // that doesn't have a user component. Such profile names are
406 // reserved for the single DefaultProfile the manager creates
407 // at startup.
408 EXPECT_EQ(Error::kInvalidArguments, TestCreateProfile(&manager, "valid"));
409
410 // We should succeed in creating a valid user profile.
411 const char kProfile[] = "~user/profile";
412 EXPECT_EQ(Error::kSuccess, TestCreateProfile(&manager, kProfile));
413
414 // We should fail in creating it a second time (already exists).
415 EXPECT_EQ(Error::kAlreadyExists, TestCreateProfile(&manager, kProfile));
416}
417
418TEST_F(ManagerTest, PushPopProfile) {
419 // It's much easier to use real Glib in creating a Manager for this
420 // test here since we want the storage side-effects.
421 GLib glib;
422 ScopedTempDir temp_dir;
423 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
424 Manager manager(control_interface(),
425 dispatcher(),
426 &glib,
427 run_path(),
428 storage_path(),
429 temp_dir.path().value());
430
431 // Pushing an invalid profile should fail.
432 EXPECT_EQ(Error::kInvalidArguments, TestPushProfile(&manager, ""));
433
434 // Pushing a default profile name should fail.
435 EXPECT_EQ(Error::kInvalidArguments, TestPushProfile(&manager, "default"));
436
437 const char kProfile0[] = "~user/profile0";
438 const char kProfile1[] = "~user/profile1";
439
440 // Create a couple of profiles.
441 ASSERT_EQ(Error::kSuccess, TestCreateProfile(&manager, kProfile0));
442 ASSERT_EQ(Error::kSuccess, TestCreateProfile(&manager, kProfile1));
443
444 // Push these profiles on the stack.
445 EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager, kProfile0));
446 EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager, kProfile1));
447
448 // Pushing a profile a second time should fail.
449 EXPECT_EQ(Error::kAlreadyExists, TestPushProfile(&manager, kProfile0));
450 EXPECT_EQ(Error::kAlreadyExists, TestPushProfile(&manager, kProfile1));
451
452 // Active profile should be the last one we pushed.
453 EXPECT_EQ(kProfile1, "~" + manager.GetActiveProfileName());
454
455 // Make sure a profile name that doesn't exist fails.
456 const char kProfile2Id[] = "profile2";
457 const string kProfile2 = base::StringPrintf("~user/%s", kProfile2Id);
458 EXPECT_EQ(Error::kNotFound, TestPushProfile(&manager, kProfile2));
459
460 // Create a new service, with a specific storage name.
461 scoped_refptr<MockService> service(
462 new NiceMock<MockService>(control_interface(),
463 dispatcher(),
464 &manager));
465 const char kServiceName[] = "service_storage_name";
466 EXPECT_CALL(*service.get(), GetStorageIdentifier())
467 .WillRepeatedly(Return(kServiceName));
468 EXPECT_CALL(*service.get(), Load(_))
469 .WillRepeatedly(Return(true));
470
471 // Add this service to the manager -- it should end up in the ephemeral
472 // profile.
473 manager.RegisterService(service);
474 ASSERT_EQ(manager.ephemeral_profile_, service->profile());
475
476 // Create storage for a profile that contains the service storage name.
477 ASSERT_TRUE(CreateBackingStoreForService(&temp_dir, kProfile2Id,
478 kServiceName));
479
480 // When we push the profile, the service should move away from the
481 // ephemeral profile to this new profile since it has an entry for
482 // this service.
483 EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager, kProfile2));
484 EXPECT_NE(manager.ephemeral_profile_, service->profile());
485 EXPECT_EQ(kProfile2, "~" + service->profile()->GetFriendlyName());
486
487 // Insert another profile that should supersede ownership of the service.
488 const char kProfile3Id[] = "profile3";
489 const string kProfile3 = base::StringPrintf("~user/%s", kProfile3Id);
490 ASSERT_TRUE(CreateBackingStoreForService(&temp_dir, kProfile3Id,
491 kServiceName));
492 EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager, kProfile3));
493 EXPECT_EQ(kProfile3, "~" + service->profile()->GetFriendlyName());
494
495 // Popping an invalid profile name should fail.
496 EXPECT_EQ(Error::kInvalidArguments, TestPopProfile(&manager, "~"));
497
498 // Popping an profile that is not at the top of the stack should fail.
499 EXPECT_EQ(Error::kNotSupported, TestPopProfile(&manager, kProfile0));
500
501 // Popping the top profile should succeed.
502 EXPECT_EQ(Error::kSuccess, TestPopProfile(&manager, kProfile3));
503
504 // Moreover the service should have switched profiles to profile 2.
505 EXPECT_EQ(kProfile2, "~" + service->profile()->GetFriendlyName());
506
507 // Popping the top profile should succeed.
508 EXPECT_EQ(Error::kSuccess, TestPopAnyProfile(&manager));
509
510 // The service should now revert to the ephemeral profile.
511 EXPECT_EQ(manager.ephemeral_profile_, service->profile());
512
513 // Pop the remaining two services off the stack.
514 EXPECT_EQ(Error::kSuccess, TestPopAnyProfile(&manager));
515 EXPECT_EQ(Error::kSuccess, TestPopAnyProfile(&manager));
516
517 // Next pop should fail with "stack is empty".
518 EXPECT_EQ(Error::kNotFound, TestPopAnyProfile(&manager));
519}
520
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700521TEST_F(ManagerTest, Dispatch) {
Chris Masonea8a2c252011-06-27 22:16:30 -0700522 {
523 ::DBus::Error error;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700524 EXPECT_TRUE(DBusAdaptor::DispatchOnType(manager()->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -0700525 flimflam::kOfflineModeProperty,
526 PropertyStoreTest::kBoolV,
527 &error));
528 }
529 {
530 ::DBus::Error error;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700531 EXPECT_TRUE(DBusAdaptor::DispatchOnType(manager()->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -0700532 flimflam::kCountryProperty,
533 PropertyStoreTest::kStringV,
534 &error));
535 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700536 // Attempt to write with value of wrong type should return InvalidArgs.
Chris Masonea8a2c252011-06-27 22:16:30 -0700537 {
538 ::DBus::Error error;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700539 EXPECT_FALSE(DBusAdaptor::DispatchOnType(manager()->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -0700540 flimflam::kCountryProperty,
541 PropertyStoreTest::kBoolV,
542 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700543 EXPECT_EQ(invalid_args(), error.name());
Chris Masonea8a2c252011-06-27 22:16:30 -0700544 }
545 {
546 ::DBus::Error error;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700547 EXPECT_FALSE(DBusAdaptor::DispatchOnType(manager()->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -0700548 flimflam::kOfflineModeProperty,
549 PropertyStoreTest::kStringV,
550 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700551 EXPECT_EQ(invalid_args(), error.name());
Chris Masonea8a2c252011-06-27 22:16:30 -0700552 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700553 // Attempt to write R/O property should return InvalidArgs.
Chris Masonea8a2c252011-06-27 22:16:30 -0700554 {
555 ::DBus::Error error;
556 EXPECT_FALSE(DBusAdaptor::DispatchOnType(
mukesh agrawalde29fa82011-09-16 16:16:36 -0700557 manager()->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -0700558 flimflam::kEnabledTechnologiesProperty,
559 PropertyStoreTest::kStringsV,
560 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700561 EXPECT_EQ(invalid_args(), error.name());
Chris Masonea8a2c252011-06-27 22:16:30 -0700562 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700563}
564
mukesh agrawal32399322011-09-01 10:53:43 -0700565TEST_F(ManagerTest, RequestScan) {
566 {
567 Error error;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700568 manager()->RegisterDevice(mock_devices_[0].get());
569 manager()->RegisterDevice(mock_devices_[1].get());
570 EXPECT_CALL(*mock_devices_[0], TechnologyIs(Technology::kWifi))
mukesh agrawal32399322011-09-01 10:53:43 -0700571 .WillRepeatedly(Return(true));
Paul Stewart22aa71b2011-09-16 12:15:11 -0700572 EXPECT_CALL(*mock_devices_[0], Scan(_));
573 EXPECT_CALL(*mock_devices_[1], TechnologyIs(Technology::kWifi))
mukesh agrawal32399322011-09-01 10:53:43 -0700574 .WillRepeatedly(Return(false));
Paul Stewart22aa71b2011-09-16 12:15:11 -0700575 EXPECT_CALL(*mock_devices_[1], Scan(_)).Times(0);
Chris Masone9d779932011-08-25 16:33:41 -0700576 manager()->RequestScan(flimflam::kTypeWifi, &error);
mukesh agrawal32399322011-09-01 10:53:43 -0700577 }
578
579 {
580 Error error;
Chris Masone9d779932011-08-25 16:33:41 -0700581 manager()->RequestScan("bogus_device_type", &error);
mukesh agrawal32399322011-09-01 10:53:43 -0700582 EXPECT_EQ(Error::kInvalidArguments, error.type());
583 }
584}
585
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700586TEST_F(ManagerTest, GetWifiServiceNoDevice) {
587 KeyValueStore args;
588 Error e;
589 manager()->GetWifiService(args, &e);
590 EXPECT_EQ(Error::kInvalidArguments, e.type());
591 EXPECT_EQ("no wifi devices available", e.message());
592}
593
594TEST_F(ManagerTest, GetWifiService) {
595 KeyValueStore args;
596 Error e;
597 WiFiServiceRefPtr wifi_service;
598
599 manager()->RegisterDevice(mock_wifi_);
600 EXPECT_CALL(*mock_wifi_, GetService(_, _))
601 .WillRepeatedly(Return(wifi_service));
602 manager()->GetWifiService(args, &e);
603}
604
Paul Stewart22aa71b2011-09-16 12:15:11 -0700605TEST_F(ManagerTest, TechnologyOrder) {
606 Error error;
607 manager()->SetTechnologyOrder(string(flimflam::kTypeEthernet) + "," +
608 string(flimflam::kTypeWifi), &error);
609 ASSERT_TRUE(error.IsSuccess());
610 EXPECT_EQ(manager()->GetTechnologyOrder(),
611 string(flimflam::kTypeEthernet) + "," +
612 string(flimflam::kTypeWifi));
613
614 manager()->SetTechnologyOrder(string(flimflam::kTypeEthernet) + "x," +
615 string(flimflam::kTypeWifi), &error);
616 ASSERT_FALSE(error.IsSuccess());
617 EXPECT_EQ(Error::kInvalidArguments, error.type());
618 EXPECT_EQ(string(flimflam::kTypeEthernet) + "," +
619 string(flimflam::kTypeWifi),
620 manager()->GetTechnologyOrder());
621}
622
623TEST_F(ManagerTest, SortServices) {
624 scoped_refptr<MockService> mock_service0(
625 new NiceMock<MockService>(control_interface(),
626 dispatcher(),
627 manager()));
628 scoped_refptr<MockService> mock_service1(
629 new NiceMock<MockService>(control_interface(),
630 dispatcher(),
631 manager()));
632 string service1_name(mock_service0->UniqueName());
633 string service2_name(mock_service1->UniqueName());
634
635 manager()->RegisterService(mock_service0);
636 manager()->RegisterService(mock_service1);
637
638 // Services should already be sorted by UniqueName
639 EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
640
641 // Asking explictly to sort services should not change anything
642 manager()->SortServices();
643 EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
644
645 // Two otherwise equal services should be reordered by strength
646 mock_service1->set_strength(1);
647 manager()->UpdateService(mock_service1);
648 EXPECT_TRUE(ServiceOrderIs(mock_service1, mock_service0));
649
650 // Security
651 mock_service0->set_security(1);
652 manager()->UpdateService(mock_service0);
653 EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
654
655 // Technology
656 EXPECT_CALL(*mock_service0.get(), TechnologyIs(Technology::kWifi))
657 .WillRepeatedly(Return(true));
658 EXPECT_CALL(*mock_service1.get(), TechnologyIs(Technology::kEthernet))
659 .WillRepeatedly(Return(true));
660 // NB: Redefine default (false) return values so we don't use the default rule
661 // which makes the logs noisier
662 EXPECT_CALL(*mock_service0.get(), TechnologyIs(Ne(Technology::kWifi)))
663 .WillRepeatedly(Return(false));
664 EXPECT_CALL(*mock_service1.get(), TechnologyIs(Ne(Technology::kEthernet)))
665 .WillRepeatedly(Return(false));
666
667 Error error;
668 manager()->SetTechnologyOrder(string(flimflam::kTypeEthernet) + "," +
669 string(flimflam::kTypeWifi), &error);
670 EXPECT_TRUE(error.IsSuccess());
671 EXPECT_TRUE(ServiceOrderIs(mock_service1, mock_service0));
672
673 manager()->SetTechnologyOrder(string(flimflam::kTypeWifi) + "," +
674 string(flimflam::kTypeEthernet), &error);
675 EXPECT_TRUE(error.IsSuccess());
676 EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
677
678 // Priority
679 mock_service0->set_priority(1);
680 manager()->UpdateService(mock_service0);
681 EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
682
683 // Favorite
684 mock_service1->set_favorite(true);
685 manager()->UpdateService(mock_service1);
686 EXPECT_TRUE(ServiceOrderIs(mock_service1, mock_service0));
687
688 // Connecting
689 EXPECT_CALL(*mock_service0.get(), state())
690 .WillRepeatedly(Return(Service::kStateAssociating));
691 manager()->UpdateService(mock_service0);
692 EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
693
694 // Connected
695 EXPECT_CALL(*mock_service1.get(), state())
696 .WillRepeatedly(Return(Service::kStateConnected));
697 manager()->UpdateService(mock_service1);
698 EXPECT_TRUE(ServiceOrderIs(mock_service1, mock_service0));
699
700 manager()->DeregisterService(mock_service0);
701 manager()->DeregisterService(mock_service1);
702}
703
Thieu Le1271d682011-11-02 22:48:19 +0000704TEST_F(ManagerTest, DisconnectServicesOnStop) {
705 scoped_refptr<MockService> mock_service(
706 new NiceMock<MockService>(control_interface(),
707 dispatcher(),
708 manager()));
709 manager()->RegisterService(mock_service);
710 EXPECT_CALL(*mock_service.get(), Disconnect()).Times(1);
711 manager()->Stop();
712}
713
Chris Masone9be4a9d2011-05-16 15:44:09 -0700714} // namespace shill