1 // Copyright (c) 2012 The Chromium 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.
5 #include "chromeos/network/shill_property_handler.h"
11 #include "base/bind.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop.h"
14 #include "base/values.h"
15 #include "chromeos/dbus/dbus_thread_manager.h"
16 #include "chromeos/dbus/shill_device_client.h"
17 #include "chromeos/dbus/shill_manager_client.h"
18 #include "chromeos/dbus/shill_service_client.h"
19 #include "dbus/object_path.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "third_party/cros_system_api/dbus/service_constants.h"
27 void ErrorCallbackFunction(const std::string
& error_name
,
28 const std::string
& error_message
) {
29 LOG(ERROR
) << "Shill Error: " << error_name
<< " : " << error_message
;
32 class TestListener
: public internal::ShillPropertyHandler::Listener
{
34 TestListener() : manager_updates_(0), errors_(0) {
37 virtual void UpdateManagedList(ManagedState::ManagedType type
,
38 const base::ListValue
& entries
) OVERRIDE
{
39 UpdateEntries(GetTypeString(type
), entries
);
42 virtual void UpdateAvailableTechnologies(
43 const base::ListValue
& technologies
) OVERRIDE
{
44 UpdateEntries(flimflam::kAvailableTechnologiesProperty
, technologies
);
47 virtual void UpdateEnabledTechnologies(
48 const base::ListValue
& technologies
) OVERRIDE
{
49 UpdateEntries(flimflam::kEnabledTechnologiesProperty
, technologies
);
52 virtual void UpdateManagedStateProperties(
53 ManagedState::ManagedType type
,
54 const std::string
& path
,
55 const base::DictionaryValue
& properties
) OVERRIDE
{
56 AddPropertyUpdate(GetTypeString(type
), path
);
59 virtual void UpdateNetworkServiceProperty(
60 const std::string
& service_path
,
61 const std::string
& key
,
62 const base::Value
& value
) OVERRIDE
{
63 AddPropertyUpdate(flimflam::kServicesProperty
, service_path
);
66 virtual void ManagerPropertyChanged() OVERRIDE
{
70 virtual void UpdateNetworkServiceIPAddress(
71 const std::string
& service_path
,
72 const std::string
& ip_address
) OVERRIDE
{
73 AddPropertyUpdate(flimflam::kServicesProperty
, service_path
);
76 virtual void ManagedStateListChanged(
77 ManagedState::ManagedType type
) OVERRIDE
{
78 AddStateListUpdate(GetTypeString(type
));
81 std::vector
<std::string
>& entries(const std::string
& type
) {
82 return entries_
[type
];
84 std::map
<std::string
, int>& property_updates(const std::string
& type
) {
85 return property_updates_
[type
];
87 int list_updates(const std::string
& type
) { return list_updates_
[type
]; }
88 int manager_updates() { return manager_updates_
; }
89 int errors() { return errors_
; }
92 std::string
GetTypeString(ManagedState::ManagedType type
) {
93 if (type
== ManagedState::MANAGED_TYPE_NETWORK
) {
94 return flimflam::kServicesProperty
;
95 } else if (type
== ManagedState::MANAGED_TYPE_DEVICE
) {
96 return flimflam::kDevicesProperty
;
98 LOG(ERROR
) << "UpdateManagedList called with unrecognized type: " << type
;
100 return std::string();
103 void UpdateEntries(const std::string
& type
, const base::ListValue
& entries
) {
106 entries_
[type
].clear();
107 for (base::ListValue::const_iterator iter
= entries
.begin();
108 iter
!= entries
.end(); ++iter
) {
110 if ((*iter
)->GetAsString(&path
))
111 entries_
[type
].push_back(path
);
115 void AddPropertyUpdate(const std::string
& type
, const std::string
& path
) {
118 property_updates(type
)[path
] += 1;
121 void AddStateListUpdate(const std::string
& type
) {
124 list_updates_
[type
] += 1;
127 // Map of list-type -> paths
128 std::map
<std::string
, std::vector
<std::string
> > entries_
;
129 // Map of list-type -> map of paths -> update counts
130 std::map
<std::string
, std::map
<std::string
, int> > property_updates_
;
131 // Map of list-type -> list update counts
132 std::map
<std::string
, int > list_updates_
;
133 int manager_updates_
;
139 class ShillPropertyHandlerTest
: public testing::Test
{
141 ShillPropertyHandlerTest()
142 : manager_test_(NULL
),
144 service_test_(NULL
) {
146 virtual ~ShillPropertyHandlerTest() {
149 virtual void SetUp() OVERRIDE
{
150 // Initialize DBusThreadManager with a stub implementation.
151 DBusThreadManager::InitializeWithStub();
152 // Get the test interface for manager / device / service and clear the
153 // default stub properties.
155 DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface();
156 ASSERT_TRUE(manager_test_
);
158 DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface();
159 ASSERT_TRUE(device_test_
);
161 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
162 ASSERT_TRUE(service_test_
);
165 virtual void TearDown() OVERRIDE
{
166 shill_property_handler_
.reset();
168 DBusThreadManager::Shutdown();
171 void AddDevice(const std::string
& type
, const std::string
& id
) {
172 ASSERT_TRUE(IsValidType(type
));
173 manager_test_
->AddDevice(id
);
174 device_test_
->AddDevice(id
, type
, std::string("/device/" + id
), "/stub");
177 void RemoveDevice(const std::string
& id
) {
178 manager_test_
->RemoveDevice(id
);
179 device_test_
->RemoveDevice(id
);
182 void AddService(const std::string
& type
,
183 const std::string
& id
,
184 const std::string
& state
,
185 bool add_to_watch_list
) {
186 ASSERT_TRUE(IsValidType(type
));
187 manager_test_
->AddService(id
, add_to_watch_list
);
188 service_test_
->AddService(id
, id
, type
, state
);
191 void RemoveService(const std::string
& id
) {
192 manager_test_
->RemoveService(id
);
193 service_test_
->RemoveService(id
);
196 // Call this after any initial Shill client setup
197 void SetupShillPropertyHandler() {
198 listener_
.reset(new TestListener
);
199 shill_property_handler_
.reset(
200 new internal::ShillPropertyHandler(listener_
.get()));
201 shill_property_handler_
->Init();
204 bool IsValidType(const std::string
& type
) {
205 return (type
== flimflam::kTypeEthernet
||
206 type
== flimflam::kTypeWifi
||
207 type
== flimflam::kTypeWimax
||
208 type
== flimflam::kTypeBluetooth
||
209 type
== flimflam::kTypeCellular
||
210 type
== flimflam::kTypeVPN
);
214 MessageLoopForUI message_loop_
;
215 scoped_ptr
<TestListener
> listener_
;
216 scoped_ptr
<internal::ShillPropertyHandler
> shill_property_handler_
;
217 ShillManagerClient::TestInterface
* manager_test_
;
218 ShillDeviceClient::TestInterface
* device_test_
;
219 ShillServiceClient::TestInterface
* service_test_
;
222 DISALLOW_COPY_AND_ASSIGN(ShillPropertyHandlerTest
);
225 TEST_F(ShillPropertyHandlerTest
, ShillPropertyHandlerStub
) {
226 SetupShillPropertyHandler();
227 message_loop_
.RunUntilIdle();
228 EXPECT_EQ(1, listener_
->manager_updates());
229 // ShillManagerClient default stub entries are in shill_manager_client.cc.
230 // TODO(stevenjb): Eliminate default stub entries and add them explicitly.
231 const size_t kNumShillManagerClientStubImplTechnologies
= 3;
232 EXPECT_EQ(kNumShillManagerClientStubImplTechnologies
,
234 flimflam::kAvailableTechnologiesProperty
).size());
235 EXPECT_EQ(kNumShillManagerClientStubImplTechnologies
,
237 flimflam::kEnabledTechnologiesProperty
).size());
238 const size_t kNumShillManagerClientStubImplDevices
= 2;
239 EXPECT_EQ(kNumShillManagerClientStubImplDevices
,
240 listener_
->entries(flimflam::kDevicesProperty
).size());
241 const size_t kNumShillManagerClientStubImplServices
= 4;
242 EXPECT_EQ(kNumShillManagerClientStubImplServices
,
243 listener_
->entries(flimflam::kServicesProperty
).size());
245 EXPECT_EQ(0, listener_
->errors());
248 TEST_F(ShillPropertyHandlerTest
, ShillPropertyHandlerTechnologyChanged
) {
249 // This relies on the stub dbus implementations for ShillManagerClient,
250 SetupShillPropertyHandler();
251 message_loop_
.RunUntilIdle();
252 EXPECT_EQ(1, listener_
->manager_updates());
253 // Add a disabled technology.
254 manager_test_
->AddTechnology(flimflam::kTypeWimax
, false);
255 message_loop_
.RunUntilIdle();
256 EXPECT_EQ(2, listener_
->manager_updates());
257 const size_t kNumShillManagerClientStubImplTechnologies
= 3;
258 EXPECT_EQ(kNumShillManagerClientStubImplTechnologies
+ 1,
260 flimflam::kAvailableTechnologiesProperty
).size());
261 EXPECT_EQ(kNumShillManagerClientStubImplTechnologies
,
263 flimflam::kEnabledTechnologiesProperty
).size());
264 // Enable the technology.
265 DBusThreadManager::Get()->GetShillManagerClient()->EnableTechnology(
266 flimflam::kTypeWimax
,
267 base::Bind(&base::DoNothing
), base::Bind(&ErrorCallbackFunction
));
268 message_loop_
.RunUntilIdle();
269 EXPECT_EQ(3, listener_
->manager_updates());
270 EXPECT_EQ(kNumShillManagerClientStubImplTechnologies
+ 1,
272 flimflam::kEnabledTechnologiesProperty
).size());
274 EXPECT_EQ(0, listener_
->errors());
277 TEST_F(ShillPropertyHandlerTest
, ShillPropertyHandlerDevicePropertyChanged
) {
278 // This relies on the stub dbus implementations for ShillManagerClient,
279 SetupShillPropertyHandler();
280 message_loop_
.RunUntilIdle();
281 EXPECT_EQ(1, listener_
->manager_updates());
282 EXPECT_EQ(1, listener_
->list_updates(flimflam::kDevicesProperty
));
283 const size_t kNumShillManagerClientStubImplDevices
= 2;
284 EXPECT_EQ(kNumShillManagerClientStubImplDevices
,
285 listener_
->entries(flimflam::kDevicesProperty
).size());
287 const std::string
kTestDevicePath("test_wifi_device1");
288 AddDevice(flimflam::kTypeWifi
, kTestDevicePath
);
289 message_loop_
.RunUntilIdle();
290 EXPECT_EQ(1, listener_
->manager_updates()); // No new manager updates.
291 EXPECT_EQ(2, listener_
->list_updates(flimflam::kDevicesProperty
));
292 EXPECT_EQ(kNumShillManagerClientStubImplDevices
+ 1,
293 listener_
->entries(flimflam::kDevicesProperty
).size());
294 // Device changes are not observed.
296 RemoveDevice(kTestDevicePath
);
297 message_loop_
.RunUntilIdle();
298 EXPECT_EQ(3, listener_
->list_updates(flimflam::kDevicesProperty
));
299 EXPECT_EQ(kNumShillManagerClientStubImplDevices
,
300 listener_
->entries(flimflam::kDevicesProperty
).size());
302 EXPECT_EQ(0, listener_
->errors());
305 TEST_F(ShillPropertyHandlerTest
, ShillPropertyHandlerServicePropertyChanged
) {
306 // This relies on the stub dbus implementations for ShillManagerClient,
307 SetupShillPropertyHandler();
308 message_loop_
.RunUntilIdle();
309 EXPECT_EQ(1, listener_
->manager_updates());
310 EXPECT_EQ(1, listener_
->list_updates(flimflam::kServicesProperty
));
311 const size_t kNumShillManagerClientStubImplServices
= 4;
312 EXPECT_EQ(kNumShillManagerClientStubImplServices
,
313 listener_
->entries(flimflam::kServicesProperty
).size());
315 // Add an unwatched service.
316 const std::string
kTestServicePath("test_wifi_service1");
317 AddService(flimflam::kTypeWifi
, kTestServicePath
,
318 flimflam::kStateIdle
, false);
319 message_loop_
.RunUntilIdle();
320 EXPECT_EQ(1, listener_
->manager_updates()); // No new manager updates.
321 EXPECT_EQ(2, listener_
->list_updates(flimflam::kServicesProperty
));
322 EXPECT_EQ(kNumShillManagerClientStubImplServices
+ 1,
323 listener_
->entries(flimflam::kServicesProperty
).size());
324 // Change a property.
325 base::FundamentalValue
scan_interval(3);
326 DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
327 dbus::ObjectPath(kTestServicePath
),
328 flimflam::kScanIntervalProperty
,
330 base::Bind(&base::DoNothing
), base::Bind(&ErrorCallbackFunction
));
331 message_loop_
.RunUntilIdle();
332 // Property change should NOT trigger an update.
333 EXPECT_EQ(0, listener_
->
334 property_updates(flimflam::kServicesProperty
)[kTestServicePath
]);
336 // Add the existing service to the watch list.
337 AddService(flimflam::kTypeWifi
, kTestServicePath
,
338 flimflam::kStateIdle
, true);
339 message_loop_
.RunUntilIdle();
340 // Service list update should be received when watch list changes.
341 EXPECT_EQ(3, listener_
->list_updates(flimflam::kServicesProperty
));
342 // Number of services shouldn't change.
343 EXPECT_EQ(kNumShillManagerClientStubImplServices
+ 1,
344 listener_
->entries(flimflam::kServicesProperty
).size());
345 // Property update should be received when watched service is added.
346 EXPECT_EQ(1, listener_
->
347 property_updates(flimflam::kServicesProperty
)[kTestServicePath
]);
349 // Change a property.
350 DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
351 dbus::ObjectPath(kTestServicePath
),
352 flimflam::kScanIntervalProperty
,
354 base::Bind(&base::DoNothing
), base::Bind(&ErrorCallbackFunction
));
355 message_loop_
.RunUntilIdle();
356 // Property change should trigger another update.
357 EXPECT_EQ(2, listener_
->
358 property_updates(flimflam::kServicesProperty
)[kTestServicePath
]);
361 RemoveService(kTestServicePath
);
362 message_loop_
.RunUntilIdle();
363 EXPECT_EQ(4, listener_
->list_updates(flimflam::kServicesProperty
));
364 EXPECT_EQ(kNumShillManagerClientStubImplServices
,
365 listener_
->entries(flimflam::kServicesProperty
).size());
367 EXPECT_EQ(0, listener_
->errors());
370 // TODO(stevenjb): Test IP Configs.
372 } // namespace chromeos