blob: bf440cbcbe4088aedec8bcd3c9dfd1173f3361c2 [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
Paul Stewarta41e38d2011-11-11 07:47:29 -0800176TEST_F(ManagerTest, DeviceRegistrationAndStart) {
177 manager()->running_ = true;
178 mock_devices_[0]->powered_ = true;
179 mock_devices_[1]->powered_ = false;
180 EXPECT_CALL(*mock_devices_[0].get(), Start())
181 .Times(1);
182 EXPECT_CALL(*mock_devices_[1].get(), Start())
183 .Times(0);
184 manager()->RegisterDevice(mock_devices_[0]);
185 manager()->RegisterDevice(mock_devices_[1]);
186}
187
188TEST_F(ManagerTest, DeviceRegistrationWithProfile) {
189 MockProfile *profile = new MockProfile(control_interface(), manager(), "");
190 DeviceRefPtr device_ref(mock_devices_[0].get());
191 AdoptProfile(manager(), profile); // Passes ownership.
192 EXPECT_CALL(*profile, ConfigureDevice(device_ref));
193 EXPECT_CALL(*profile, Save());
194 manager()->RegisterDevice(mock_devices_[0]);
195}
196
Chris Masone9be4a9d2011-05-16 15:44:09 -0700197TEST_F(ManagerTest, DeviceDeregistration) {
Paul Stewart22aa71b2011-09-16 12:15:11 -0700198 ON_CALL(*mock_devices_[0].get(), TechnologyIs(Technology::kEthernet))
Chris Masone3c3f6a12011-07-01 10:01:41 -0700199 .WillByDefault(Return(true));
Paul Stewart22aa71b2011-09-16 12:15:11 -0700200 ON_CALL(*mock_devices_[1].get(), TechnologyIs(Technology::kWifi))
Chris Masone9be4a9d2011-05-16 15:44:09 -0700201 .WillByDefault(Return(true));
202
Paul Stewart22aa71b2011-09-16 12:15:11 -0700203 manager()->RegisterDevice(mock_devices_[0].get());
204 manager()->RegisterDevice(mock_devices_[1].get());
Chris Masone9be4a9d2011-05-16 15:44:09 -0700205
Paul Stewart22aa71b2011-09-16 12:15:11 -0700206 ASSERT_TRUE(IsDeviceRegistered(mock_devices_[0], Technology::kEthernet));
207 ASSERT_TRUE(IsDeviceRegistered(mock_devices_[1], Technology::kWifi));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700208
Paul Stewart22aa71b2011-09-16 12:15:11 -0700209 EXPECT_CALL(*mock_devices_[0].get(), Stop());
210 manager()->DeregisterDevice(mock_devices_[0].get());
211 EXPECT_FALSE(IsDeviceRegistered(mock_devices_[0], Technology::kEthernet));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700212
Paul Stewart22aa71b2011-09-16 12:15:11 -0700213 EXPECT_CALL(*mock_devices_[1].get(), Stop());
214 manager()->DeregisterDevice(mock_devices_[1].get());
215 EXPECT_FALSE(IsDeviceRegistered(mock_devices_[1], Technology::kWifi));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700216}
217
218TEST_F(ManagerTest, ServiceRegistration) {
Chris Masone9d779932011-08-25 16:33:41 -0700219 // It's much easier and safer to use a real GLib for this test.
220 GLib glib;
Chris Masone2176a882011-09-14 22:29:15 -0700221 Manager manager(control_interface(),
222 dispatcher(),
Chris Masone9d779932011-08-25 16:33:41 -0700223 &glib,
224 run_path(),
225 storage_path(),
226 string());
Chris Masone6515aab2011-10-12 16:19:09 -0700227 ProfileRefPtr profile(CreateProfileForManager(&manager, &glib));
228 ASSERT_TRUE(profile.get());
Paul Stewarta849a3d2011-11-03 05:54:09 -0700229 AdoptProfile(&manager, profile);
Chris Masone6515aab2011-10-12 16:19:09 -0700230
Chris Masone9be4a9d2011-05-16 15:44:09 -0700231 scoped_refptr<MockService> mock_service(
Chris Masone2176a882011-09-14 22:29:15 -0700232 new NiceMock<MockService>(control_interface(),
233 dispatcher(),
Chris Masone9d779932011-08-25 16:33:41 -0700234 &manager));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700235 scoped_refptr<MockService> mock_service2(
Chris Masone2176a882011-09-14 22:29:15 -0700236 new NiceMock<MockService>(control_interface(),
237 dispatcher(),
Chris Masone9d779932011-08-25 16:33:41 -0700238 &manager));
mukesh agrawal51a7e932011-07-27 16:18:26 -0700239 string service1_name(mock_service->UniqueName());
240 string service2_name(mock_service2->UniqueName());
241
242 EXPECT_CALL(*mock_service.get(), GetRpcIdentifier())
243 .WillRepeatedly(Return(service1_name));
Chris Masone6791a432011-07-12 13:23:19 -0700244 EXPECT_CALL(*mock_service2.get(), GetRpcIdentifier())
mukesh agrawal51a7e932011-07-27 16:18:26 -0700245 .WillRepeatedly(Return(service2_name));
mukesh agrawal32399322011-09-01 10:53:43 -0700246 // TODO(quiche): make this EXPECT_CALL work (crosbug.com/20154)
Chris Masone9d779932011-08-25 16:33:41 -0700247 // EXPECT_CALL(*dynamic_cast<ManagerMockAdaptor *>(manager.adaptor_.get()),
mukesh agrawal32399322011-09-01 10:53:43 -0700248 // EmitRpcIdentifierArrayChanged(flimflam::kServicesProperty, _));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700249
Chris Masone9d779932011-08-25 16:33:41 -0700250 manager.RegisterService(mock_service);
251 manager.RegisterService(mock_service2);
Chris Masone9be4a9d2011-05-16 15:44:09 -0700252
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800253 Error error;
254 vector<string> rpc_ids = manager.EnumerateAvailableServices(&error);
Chris Masone6791a432011-07-12 13:23:19 -0700255 set<string> ids(rpc_ids.begin(), rpc_ids.end());
mukesh agrawal51a7e932011-07-27 16:18:26 -0700256 EXPECT_EQ(2, ids.size());
257 EXPECT_TRUE(ContainsKey(ids, mock_service->GetRpcIdentifier()));
258 EXPECT_TRUE(ContainsKey(ids, mock_service2->GetRpcIdentifier()));
Chris Masone6791a432011-07-12 13:23:19 -0700259
Chris Masone9d779932011-08-25 16:33:41 -0700260 EXPECT_TRUE(manager.FindService(service1_name).get() != NULL);
261 EXPECT_TRUE(manager.FindService(service2_name).get() != NULL);
262
263 manager.Stop();
Chris Masone9be4a9d2011-05-16 15:44:09 -0700264}
265
Chris Masone6515aab2011-10-12 16:19:09 -0700266TEST_F(ManagerTest, RegisterKnownService) {
267 // It's much easier and safer to use a real GLib for this test.
268 GLib glib;
269 Manager manager(control_interface(),
270 dispatcher(),
271 &glib,
272 run_path(),
273 storage_path(),
274 string());
275 ProfileRefPtr profile(CreateProfileForManager(&manager, &glib));
276 ASSERT_TRUE(profile.get());
Paul Stewarta849a3d2011-11-03 05:54:09 -0700277 AdoptProfile(&manager, profile);
Chris Masone6515aab2011-10-12 16:19:09 -0700278 {
279 ServiceRefPtr service1(new ServiceUnderTest(control_interface(),
280 dispatcher(),
281 &manager));
Chris Masone6515aab2011-10-12 16:19:09 -0700282 ASSERT_TRUE(profile->AdoptService(service1));
283 ASSERT_TRUE(profile->ContainsService(service1));
284 } // Force destruction of service1.
285
286 ServiceRefPtr service2(new ServiceUnderTest(control_interface(),
287 dispatcher(),
288 &manager));
289 manager.RegisterService(service2);
290 EXPECT_EQ(service2->profile().get(), profile.get());
291 manager.Stop();
292}
293
294TEST_F(ManagerTest, RegisterUnknownService) {
295 // It's much easier and safer to use a real GLib for this test.
296 GLib glib;
297 Manager manager(control_interface(),
298 dispatcher(),
299 &glib,
300 run_path(),
301 storage_path(),
302 string());
303 ProfileRefPtr profile(CreateProfileForManager(&manager, &glib));
304 ASSERT_TRUE(profile.get());
Paul Stewarta849a3d2011-11-03 05:54:09 -0700305 AdoptProfile(&manager, profile);
Chris Masone6515aab2011-10-12 16:19:09 -0700306 {
307 ServiceRefPtr service1(new ServiceUnderTest(control_interface(),
308 dispatcher(),
309 &manager));
Chris Masone6515aab2011-10-12 16:19:09 -0700310 ASSERT_TRUE(profile->AdoptService(service1));
311 ASSERT_TRUE(profile->ContainsService(service1));
312 } // Force destruction of service1.
313 scoped_refptr<MockService> mock_service2(
314 new NiceMock<MockService>(control_interface(),
315 dispatcher(),
316 &manager));
317 EXPECT_CALL(*mock_service2.get(), GetStorageIdentifier())
318 .WillRepeatedly(Return(mock_service2->UniqueName()));
319 manager.RegisterService(mock_service2);
320 EXPECT_NE(mock_service2->profile().get(), profile.get());
321 manager.Stop();
322}
323
Chris Masonea8a2c252011-06-27 22:16:30 -0700324TEST_F(ManagerTest, GetProperties) {
Chris Masoneb9c00592011-10-06 13:10:39 -0700325 ProfileRefPtr profile(new MockProfile(control_interface(), manager(), ""));
Paul Stewarta849a3d2011-11-03 05:54:09 -0700326 AdoptProfile(manager(), profile);
Chris Masonea8a2c252011-06-27 22:16:30 -0700327 map<string, ::DBus::Variant> props;
328 Error error(Error::kInvalidProperty, "");
329 {
330 ::DBus::Error dbus_error;
331 string expected("portal_list");
mukesh agrawalde29fa82011-09-16 16:16:36 -0700332 manager()->mutable_store()->SetStringProperty(
333 flimflam::kCheckPortalListProperty,
334 expected,
335 &error);
Chris Masone9d779932011-08-25 16:33:41 -0700336 DBusAdaptor::GetProperties(manager()->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700337 ASSERT_FALSE(props.find(flimflam::kCheckPortalListProperty) == props.end());
338 EXPECT_EQ(props[flimflam::kCheckPortalListProperty].reader().get_string(),
339 expected);
340 }
341 {
342 ::DBus::Error dbus_error;
343 bool expected = true;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700344 manager()->mutable_store()->SetBoolProperty(flimflam::kOfflineModeProperty,
345 expected,
346 &error);
Chris Masone9d779932011-08-25 16:33:41 -0700347 DBusAdaptor::GetProperties(manager()->store(), &props, &dbus_error);
Chris Masonea8a2c252011-06-27 22:16:30 -0700348 ASSERT_FALSE(props.find(flimflam::kOfflineModeProperty) == props.end());
349 EXPECT_EQ(props[flimflam::kOfflineModeProperty].reader().get_bool(),
350 expected);
351 }
352}
353
Chris Masone3c3f6a12011-07-01 10:01:41 -0700354TEST_F(ManagerTest, GetDevicesProperty) {
Chris Masoneb9c00592011-10-06 13:10:39 -0700355 ProfileRefPtr profile(new MockProfile(control_interface(), manager(), ""));
Paul Stewarta849a3d2011-11-03 05:54:09 -0700356 AdoptProfile(manager(), profile);
Paul Stewart22aa71b2011-09-16 12:15:11 -0700357 manager()->RegisterDevice(mock_devices_[0].get());
358 manager()->RegisterDevice(mock_devices_[1].get());
Chris Masone3c3f6a12011-07-01 10:01:41 -0700359 {
360 map<string, ::DBus::Variant> props;
361 ::DBus::Error dbus_error;
Chris Masone9d779932011-08-25 16:33:41 -0700362 DBusAdaptor::GetProperties(manager()->store(), &props, &dbus_error);
Chris Masone3c3f6a12011-07-01 10:01:41 -0700363 ASSERT_FALSE(props.find(flimflam::kDevicesProperty) == props.end());
364 Strings devices =
365 props[flimflam::kDevicesProperty].operator vector<string>();
366 EXPECT_EQ(2, devices.size());
367 }
Chris Masone3c3f6a12011-07-01 10:01:41 -0700368}
369
Chris Masone6791a432011-07-12 13:23:19 -0700370TEST_F(ManagerTest, MoveService) {
Chris Masone2176a882011-09-14 22:29:15 -0700371 Manager manager(control_interface(),
372 dispatcher(),
Chris Masone6515aab2011-10-12 16:19:09 -0700373 glib(),
Chris Masone9d779932011-08-25 16:33:41 -0700374 run_path(),
375 storage_path(),
376 string());
Chris Masone6515aab2011-10-12 16:19:09 -0700377 scoped_refptr<MockService> s2(new MockService(control_interface(),
378 dispatcher(),
379 &manager));
380 // Inject an actual profile, backed by a fake StoreInterface
Chris Masoneb9c00592011-10-06 13:10:39 -0700381 {
Chris Masone6515aab2011-10-12 16:19:09 -0700382 Profile::Identifier id("irrelevant");
Chris Masoneb9c00592011-10-06 13:10:39 -0700383 ProfileRefPtr profile(
384 new Profile(control_interface(), &manager, id, "", false));
385 MockStore *storage = new MockStore;
Chris Masone6515aab2011-10-12 16:19:09 -0700386 // Say we don't have |s2| the first time asked, then that we do.
387 EXPECT_CALL(*storage, ContainsGroup(s2->GetStorageIdentifier()))
388 .WillOnce(Return(false))
389 .WillRepeatedly(Return(true));
390 EXPECT_CALL(*storage, Flush())
391 .Times(AnyNumber())
392 .WillRepeatedly(Return(true));
Chris Masoneb9c00592011-10-06 13:10:39 -0700393 profile->set_storage(storage);
Paul Stewarta849a3d2011-11-03 05:54:09 -0700394 AdoptProfile(&manager, profile);
Chris Masoneb9c00592011-10-06 13:10:39 -0700395 }
Chris Masone6515aab2011-10-12 16:19:09 -0700396 // Create a profile that already has |s2| in it.
397 ProfileRefPtr profile(new EphemeralProfile(control_interface(), &manager));
398 profile->AdoptService(s2);
Chris Masone9d779932011-08-25 16:33:41 -0700399
Chris Masone6515aab2011-10-12 16:19:09 -0700400 // Now, move the Service |s2| to another profile.
401 EXPECT_CALL(*s2.get(), Save(_)).WillOnce(Return(true));
402 ASSERT_TRUE(manager.MoveServiceToProfile(s2, manager.ActiveProfile()));
Chris Masone6791a432011-07-12 13:23:19 -0700403
404 // Force destruction of the original Profile, to ensure that the Service
405 // is kept alive and populated with data.
406 profile = NULL;
Chris Masone6515aab2011-10-12 16:19:09 -0700407 ASSERT_TRUE(manager.ActiveProfile()->ContainsService(s2));
Chris Masone9d779932011-08-25 16:33:41 -0700408 manager.Stop();
Chris Masone6791a432011-07-12 13:23:19 -0700409}
410
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700411TEST_F(ManagerTest, CreateProfile) {
412 // It's much easier to use real Glib here since we want the storage
413 // side-effects.
414 GLib glib;
415 ScopedTempDir temp_dir;
416 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
417
418 Manager manager(control_interface(),
419 dispatcher(),
420 &glib,
421 run_path(),
422 storage_path(),
423 temp_dir.path().value());
424
425 // Invalid name should be rejected.
426 EXPECT_EQ(Error::kInvalidArguments, TestCreateProfile(&manager, ""));
427
428 // Valid name is still rejected because we can't create a profile
429 // that doesn't have a user component. Such profile names are
430 // reserved for the single DefaultProfile the manager creates
431 // at startup.
432 EXPECT_EQ(Error::kInvalidArguments, TestCreateProfile(&manager, "valid"));
433
434 // We should succeed in creating a valid user profile.
435 const char kProfile[] = "~user/profile";
436 EXPECT_EQ(Error::kSuccess, TestCreateProfile(&manager, kProfile));
437
438 // We should fail in creating it a second time (already exists).
439 EXPECT_EQ(Error::kAlreadyExists, TestCreateProfile(&manager, kProfile));
440}
441
442TEST_F(ManagerTest, PushPopProfile) {
443 // It's much easier to use real Glib in creating a Manager for this
444 // test here since we want the storage side-effects.
445 GLib glib;
446 ScopedTempDir temp_dir;
447 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
448 Manager manager(control_interface(),
449 dispatcher(),
450 &glib,
451 run_path(),
452 storage_path(),
453 temp_dir.path().value());
454
455 // Pushing an invalid profile should fail.
456 EXPECT_EQ(Error::kInvalidArguments, TestPushProfile(&manager, ""));
457
458 // Pushing a default profile name should fail.
459 EXPECT_EQ(Error::kInvalidArguments, TestPushProfile(&manager, "default"));
460
461 const char kProfile0[] = "~user/profile0";
462 const char kProfile1[] = "~user/profile1";
463
464 // Create a couple of profiles.
465 ASSERT_EQ(Error::kSuccess, TestCreateProfile(&manager, kProfile0));
466 ASSERT_EQ(Error::kSuccess, TestCreateProfile(&manager, kProfile1));
467
468 // Push these profiles on the stack.
469 EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager, kProfile0));
470 EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager, kProfile1));
471
472 // Pushing a profile a second time should fail.
473 EXPECT_EQ(Error::kAlreadyExists, TestPushProfile(&manager, kProfile0));
474 EXPECT_EQ(Error::kAlreadyExists, TestPushProfile(&manager, kProfile1));
475
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800476 Error error;
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700477 // Active profile should be the last one we pushed.
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800478 EXPECT_EQ(kProfile1, "~" + manager.GetActiveProfileName(&error));
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700479
480 // Make sure a profile name that doesn't exist fails.
481 const char kProfile2Id[] = "profile2";
482 const string kProfile2 = base::StringPrintf("~user/%s", kProfile2Id);
483 EXPECT_EQ(Error::kNotFound, TestPushProfile(&manager, kProfile2));
484
485 // Create a new service, with a specific storage name.
486 scoped_refptr<MockService> service(
487 new NiceMock<MockService>(control_interface(),
488 dispatcher(),
489 &manager));
490 const char kServiceName[] = "service_storage_name";
491 EXPECT_CALL(*service.get(), GetStorageIdentifier())
492 .WillRepeatedly(Return(kServiceName));
493 EXPECT_CALL(*service.get(), Load(_))
494 .WillRepeatedly(Return(true));
495
496 // Add this service to the manager -- it should end up in the ephemeral
497 // profile.
498 manager.RegisterService(service);
499 ASSERT_EQ(manager.ephemeral_profile_, service->profile());
500
501 // Create storage for a profile that contains the service storage name.
502 ASSERT_TRUE(CreateBackingStoreForService(&temp_dir, kProfile2Id,
503 kServiceName));
504
505 // When we push the profile, the service should move away from the
506 // ephemeral profile to this new profile since it has an entry for
507 // this service.
508 EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager, kProfile2));
509 EXPECT_NE(manager.ephemeral_profile_, service->profile());
510 EXPECT_EQ(kProfile2, "~" + service->profile()->GetFriendlyName());
511
512 // Insert another profile that should supersede ownership of the service.
513 const char kProfile3Id[] = "profile3";
514 const string kProfile3 = base::StringPrintf("~user/%s", kProfile3Id);
515 ASSERT_TRUE(CreateBackingStoreForService(&temp_dir, kProfile3Id,
516 kServiceName));
517 EXPECT_EQ(Error::kSuccess, TestPushProfile(&manager, kProfile3));
518 EXPECT_EQ(kProfile3, "~" + service->profile()->GetFriendlyName());
519
520 // Popping an invalid profile name should fail.
521 EXPECT_EQ(Error::kInvalidArguments, TestPopProfile(&manager, "~"));
522
523 // Popping an profile that is not at the top of the stack should fail.
524 EXPECT_EQ(Error::kNotSupported, TestPopProfile(&manager, kProfile0));
525
526 // Popping the top profile should succeed.
527 EXPECT_EQ(Error::kSuccess, TestPopProfile(&manager, kProfile3));
528
529 // Moreover the service should have switched profiles to profile 2.
530 EXPECT_EQ(kProfile2, "~" + service->profile()->GetFriendlyName());
531
532 // Popping the top profile should succeed.
533 EXPECT_EQ(Error::kSuccess, TestPopAnyProfile(&manager));
534
535 // The service should now revert to the ephemeral profile.
536 EXPECT_EQ(manager.ephemeral_profile_, service->profile());
537
538 // Pop the remaining two services off the stack.
539 EXPECT_EQ(Error::kSuccess, TestPopAnyProfile(&manager));
540 EXPECT_EQ(Error::kSuccess, TestPopAnyProfile(&manager));
541
542 // Next pop should fail with "stack is empty".
543 EXPECT_EQ(Error::kNotFound, TestPopAnyProfile(&manager));
544}
545
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700546TEST_F(ManagerTest, Dispatch) {
Chris Masonea8a2c252011-06-27 22:16:30 -0700547 {
548 ::DBus::Error error;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700549 EXPECT_TRUE(DBusAdaptor::DispatchOnType(manager()->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -0700550 flimflam::kOfflineModeProperty,
551 PropertyStoreTest::kBoolV,
552 &error));
553 }
554 {
555 ::DBus::Error error;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700556 EXPECT_TRUE(DBusAdaptor::DispatchOnType(manager()->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -0700557 flimflam::kCountryProperty,
558 PropertyStoreTest::kStringV,
559 &error));
560 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700561 // Attempt to write with value of wrong type should return InvalidArgs.
Chris Masonea8a2c252011-06-27 22:16:30 -0700562 {
563 ::DBus::Error error;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700564 EXPECT_FALSE(DBusAdaptor::DispatchOnType(manager()->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -0700565 flimflam::kCountryProperty,
566 PropertyStoreTest::kBoolV,
567 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700568 EXPECT_EQ(invalid_args(), error.name());
Chris Masonea8a2c252011-06-27 22:16:30 -0700569 }
570 {
571 ::DBus::Error error;
mukesh agrawalde29fa82011-09-16 16:16:36 -0700572 EXPECT_FALSE(DBusAdaptor::DispatchOnType(manager()->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -0700573 flimflam::kOfflineModeProperty,
574 PropertyStoreTest::kStringV,
575 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700576 EXPECT_EQ(invalid_args(), error.name());
Chris Masonea8a2c252011-06-27 22:16:30 -0700577 }
Chris Masoneb925cc82011-06-22 15:39:57 -0700578 // Attempt to write R/O property should return InvalidArgs.
Chris Masonea8a2c252011-06-27 22:16:30 -0700579 {
580 ::DBus::Error error;
581 EXPECT_FALSE(DBusAdaptor::DispatchOnType(
mukesh agrawalde29fa82011-09-16 16:16:36 -0700582 manager()->mutable_store(),
Chris Masonea8a2c252011-06-27 22:16:30 -0700583 flimflam::kEnabledTechnologiesProperty,
584 PropertyStoreTest::kStringsV,
585 &error));
Chris Masone9d779932011-08-25 16:33:41 -0700586 EXPECT_EQ(invalid_args(), error.name());
Chris Masonea8a2c252011-06-27 22:16:30 -0700587 }
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700588}
589
mukesh agrawal32399322011-09-01 10:53:43 -0700590TEST_F(ManagerTest, RequestScan) {
591 {
592 Error error;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700593 manager()->RegisterDevice(mock_devices_[0].get());
594 manager()->RegisterDevice(mock_devices_[1].get());
595 EXPECT_CALL(*mock_devices_[0], TechnologyIs(Technology::kWifi))
mukesh agrawal32399322011-09-01 10:53:43 -0700596 .WillRepeatedly(Return(true));
Paul Stewart22aa71b2011-09-16 12:15:11 -0700597 EXPECT_CALL(*mock_devices_[0], Scan(_));
598 EXPECT_CALL(*mock_devices_[1], TechnologyIs(Technology::kWifi))
mukesh agrawal32399322011-09-01 10:53:43 -0700599 .WillRepeatedly(Return(false));
Paul Stewart22aa71b2011-09-16 12:15:11 -0700600 EXPECT_CALL(*mock_devices_[1], Scan(_)).Times(0);
Chris Masone9d779932011-08-25 16:33:41 -0700601 manager()->RequestScan(flimflam::kTypeWifi, &error);
mukesh agrawal32399322011-09-01 10:53:43 -0700602 }
603
604 {
605 Error error;
Chris Masone9d779932011-08-25 16:33:41 -0700606 manager()->RequestScan("bogus_device_type", &error);
mukesh agrawal32399322011-09-01 10:53:43 -0700607 EXPECT_EQ(Error::kInvalidArguments, error.type());
608 }
609}
610
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700611TEST_F(ManagerTest, GetWifiServiceNoDevice) {
612 KeyValueStore args;
613 Error e;
614 manager()->GetWifiService(args, &e);
615 EXPECT_EQ(Error::kInvalidArguments, e.type());
616 EXPECT_EQ("no wifi devices available", e.message());
617}
618
619TEST_F(ManagerTest, GetWifiService) {
620 KeyValueStore args;
621 Error e;
622 WiFiServiceRefPtr wifi_service;
623
624 manager()->RegisterDevice(mock_wifi_);
625 EXPECT_CALL(*mock_wifi_, GetService(_, _))
626 .WillRepeatedly(Return(wifi_service));
627 manager()->GetWifiService(args, &e);
628}
629
Paul Stewart22aa71b2011-09-16 12:15:11 -0700630TEST_F(ManagerTest, TechnologyOrder) {
631 Error error;
632 manager()->SetTechnologyOrder(string(flimflam::kTypeEthernet) + "," +
633 string(flimflam::kTypeWifi), &error);
634 ASSERT_TRUE(error.IsSuccess());
635 EXPECT_EQ(manager()->GetTechnologyOrder(),
636 string(flimflam::kTypeEthernet) + "," +
637 string(flimflam::kTypeWifi));
638
639 manager()->SetTechnologyOrder(string(flimflam::kTypeEthernet) + "x," +
640 string(flimflam::kTypeWifi), &error);
641 ASSERT_FALSE(error.IsSuccess());
642 EXPECT_EQ(Error::kInvalidArguments, error.type());
643 EXPECT_EQ(string(flimflam::kTypeEthernet) + "," +
644 string(flimflam::kTypeWifi),
645 manager()->GetTechnologyOrder());
646}
647
648TEST_F(ManagerTest, SortServices) {
mukesh agrawal00917ce2011-11-22 23:56:55 +0000649 // TODO(quiche): Some of these tests would probably fit better in
650 // service_unittest, since the actual comparison of Services is
651 // implemented in Service. (crosbug.com/23370)
652
Paul Stewart22aa71b2011-09-16 12:15:11 -0700653 scoped_refptr<MockService> mock_service0(
654 new NiceMock<MockService>(control_interface(),
655 dispatcher(),
656 manager()));
657 scoped_refptr<MockService> mock_service1(
658 new NiceMock<MockService>(control_interface(),
659 dispatcher(),
660 manager()));
Paul Stewart22aa71b2011-09-16 12:15:11 -0700661
662 manager()->RegisterService(mock_service0);
663 manager()->RegisterService(mock_service1);
664
665 // Services should already be sorted by UniqueName
666 EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
667
668 // Asking explictly to sort services should not change anything
669 manager()->SortServices();
670 EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
671
672 // Two otherwise equal services should be reordered by strength
673 mock_service1->set_strength(1);
674 manager()->UpdateService(mock_service1);
675 EXPECT_TRUE(ServiceOrderIs(mock_service1, mock_service0));
676
677 // Security
Paul Stewart1ca3e852011-11-04 07:50:49 -0700678 mock_service0->set_security_level(1);
Paul Stewart22aa71b2011-09-16 12:15:11 -0700679 manager()->UpdateService(mock_service0);
680 EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
681
682 // Technology
683 EXPECT_CALL(*mock_service0.get(), TechnologyIs(Technology::kWifi))
684 .WillRepeatedly(Return(true));
685 EXPECT_CALL(*mock_service1.get(), TechnologyIs(Technology::kEthernet))
686 .WillRepeatedly(Return(true));
687 // NB: Redefine default (false) return values so we don't use the default rule
688 // which makes the logs noisier
689 EXPECT_CALL(*mock_service0.get(), TechnologyIs(Ne(Technology::kWifi)))
690 .WillRepeatedly(Return(false));
691 EXPECT_CALL(*mock_service1.get(), TechnologyIs(Ne(Technology::kEthernet)))
692 .WillRepeatedly(Return(false));
693
694 Error error;
695 manager()->SetTechnologyOrder(string(flimflam::kTypeEthernet) + "," +
696 string(flimflam::kTypeWifi), &error);
697 EXPECT_TRUE(error.IsSuccess());
698 EXPECT_TRUE(ServiceOrderIs(mock_service1, mock_service0));
699
700 manager()->SetTechnologyOrder(string(flimflam::kTypeWifi) + "," +
701 string(flimflam::kTypeEthernet), &error);
702 EXPECT_TRUE(error.IsSuccess());
703 EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
704
705 // Priority
706 mock_service0->set_priority(1);
707 manager()->UpdateService(mock_service0);
708 EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
709
710 // Favorite
mukesh agrawal00917ce2011-11-22 23:56:55 +0000711 mock_service1->MakeFavorite();
Paul Stewart22aa71b2011-09-16 12:15:11 -0700712 manager()->UpdateService(mock_service1);
713 EXPECT_TRUE(ServiceOrderIs(mock_service1, mock_service0));
714
715 // Connecting
716 EXPECT_CALL(*mock_service0.get(), state())
717 .WillRepeatedly(Return(Service::kStateAssociating));
718 manager()->UpdateService(mock_service0);
719 EXPECT_TRUE(ServiceOrderIs(mock_service0, mock_service1));
720
721 // Connected
722 EXPECT_CALL(*mock_service1.get(), state())
723 .WillRepeatedly(Return(Service::kStateConnected));
724 manager()->UpdateService(mock_service1);
725 EXPECT_TRUE(ServiceOrderIs(mock_service1, mock_service0));
726
727 manager()->DeregisterService(mock_service0);
728 manager()->DeregisterService(mock_service1);
729}
730
Thieu Le1271d682011-11-02 22:48:19 +0000731TEST_F(ManagerTest, DisconnectServicesOnStop) {
732 scoped_refptr<MockService> mock_service(
733 new NiceMock<MockService>(control_interface(),
734 dispatcher(),
735 manager()));
736 manager()->RegisterService(mock_service);
737 EXPECT_CALL(*mock_service.get(), Disconnect()).Times(1);
738 manager()->Stop();
739}
740
mukesh agrawal00917ce2011-11-22 23:56:55 +0000741TEST_F(ManagerTest, UpdateServiceConnected) {
742 scoped_refptr<MockService> mock_service(
743 new NiceMock<MockService>(control_interface(),
744 dispatcher(),
745 manager()));
746 manager()->RegisterService(mock_service);
747 EXPECT_FALSE(mock_service->favorite());
748 EXPECT_FALSE(mock_service->auto_connect());
749
750 EXPECT_CALL(*mock_service.get(), state())
751 .WillRepeatedly(Return(Service::kStateConnected));
752 manager()->UpdateService(mock_service);
753 // We can't EXPECT_CALL(..., MakeFavorite), because that requires us
754 // to mock out MakeFavorite. And mocking that out would break the
755 // SortServices test. (crosbug.com/23370)
756 EXPECT_TRUE(mock_service->favorite());
757 EXPECT_TRUE(mock_service->auto_connect());
758}
759
Chris Masone9be4a9d2011-05-16 15:44:09 -0700760} // namespace shill