blob: e151105fe01b84b03a7fca76e28d52a9fa392cbf [file] [log] [blame]
[email protected]3c8bd112012-11-07 10:14:591// 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.
4
5#include "chromeos/network/shill_property_handler.h"
6
7#include <map>
8#include <set>
9#include <string>
10
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"
22
23namespace chromeos {
24
25namespace {
26
27void ErrorCallbackFunction(const std::string& error_name,
28 const std::string& error_message) {
29 LOG(ERROR) << "Shill Error: " << error_name << " : " << error_message;
30}
31
32class TestListener : public internal::ShillPropertyHandler::Listener {
33 public:
34 TestListener() : manager_updates_(0), errors_(0) {
35 }
36
37 virtual void UpdateManagedList(ManagedState::ManagedType type,
38 const base::ListValue& entries) OVERRIDE {
39 UpdateEntries(GetTypeString(type), entries);
40 }
41
[email protected]3c8bd112012-11-07 10:14:5942 virtual void UpdateManagedStateProperties(
43 ManagedState::ManagedType type,
44 const std::string& path,
45 const base::DictionaryValue& properties) OVERRIDE {
46 AddPropertyUpdate(GetTypeString(type), path);
47 }
48
49 virtual void UpdateNetworkServiceProperty(
50 const std::string& service_path,
51 const std::string& key,
52 const base::Value& value) OVERRIDE {
53 AddPropertyUpdate(flimflam::kServicesProperty, service_path);
54 }
55
[email protected]b16d79d72013-02-07 08:14:4656 virtual void UpdateDeviceProperty(
57 const std::string& device_path,
58 const std::string& key,
59 const base::Value& value) OVERRIDE {
60 AddPropertyUpdate(flimflam::kDevicesProperty, device_path);
61 }
62
[email protected]3c8bd112012-11-07 10:14:5963 virtual void ManagerPropertyChanged() OVERRIDE {
64 ++manager_updates_;
65 }
66
67 virtual void UpdateNetworkServiceIPAddress(
68 const std::string& service_path,
69 const std::string& ip_address) OVERRIDE {
70 AddPropertyUpdate(flimflam::kServicesProperty, service_path);
71 }
72
73 virtual void ManagedStateListChanged(
74 ManagedState::ManagedType type) OVERRIDE {
75 AddStateListUpdate(GetTypeString(type));
76 }
77
78 std::vector<std::string>& entries(const std::string& type) {
79 return entries_[type];
80 }
81 std::map<std::string, int>& property_updates(const std::string& type) {
82 return property_updates_[type];
83 }
84 int list_updates(const std::string& type) { return list_updates_[type]; }
85 int manager_updates() { return manager_updates_; }
86 int errors() { return errors_; }
87
88 private:
89 std::string GetTypeString(ManagedState::ManagedType type) {
90 if (type == ManagedState::MANAGED_TYPE_NETWORK) {
91 return flimflam::kServicesProperty;
92 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
93 return flimflam::kDevicesProperty;
94 }
95 LOG(ERROR) << "UpdateManagedList called with unrecognized type: " << type;
96 ++errors_;
97 return std::string();
98 }
99
100 void UpdateEntries(const std::string& type, const base::ListValue& entries) {
101 if (type.empty())
102 return;
103 entries_[type].clear();
104 for (base::ListValue::const_iterator iter = entries.begin();
105 iter != entries.end(); ++iter) {
106 std::string path;
107 if ((*iter)->GetAsString(&path))
108 entries_[type].push_back(path);
109 }
110 }
111
112 void AddPropertyUpdate(const std::string& type, const std::string& path) {
113 if (type.empty())
114 return;
115 property_updates(type)[path] += 1;
116 }
117
118 void AddStateListUpdate(const std::string& type) {
119 if (type.empty())
120 return;
121 list_updates_[type] += 1;
122 }
123
124 // Map of list-type -> paths
125 std::map<std::string, std::vector<std::string> > entries_;
126 // Map of list-type -> map of paths -> update counts
127 std::map<std::string, std::map<std::string, int> > property_updates_;
128 // Map of list-type -> list update counts
129 std::map<std::string, int > list_updates_;
130 int manager_updates_;
131 int errors_;
132};
133
134} // namespace
135
136class ShillPropertyHandlerTest : public testing::Test {
137 public:
138 ShillPropertyHandlerTest()
139 : manager_test_(NULL),
140 device_test_(NULL),
141 service_test_(NULL) {
142 }
143 virtual ~ShillPropertyHandlerTest() {
144 }
145
146 virtual void SetUp() OVERRIDE {
147 // Initialize DBusThreadManager with a stub implementation.
148 DBusThreadManager::InitializeWithStub();
149 // Get the test interface for manager / device / service and clear the
150 // default stub properties.
151 manager_test_ =
152 DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface();
153 ASSERT_TRUE(manager_test_);
154 device_test_ =
155 DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface();
156 ASSERT_TRUE(device_test_);
157 service_test_ =
158 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
159 ASSERT_TRUE(service_test_);
160 }
161
162 virtual void TearDown() OVERRIDE {
163 shill_property_handler_.reset();
164 listener_.reset();
165 DBusThreadManager::Shutdown();
166 }
167
168 void AddDevice(const std::string& type, const std::string& id) {
169 ASSERT_TRUE(IsValidType(type));
[email protected]b7c377e2013-01-15 10:00:39170 device_test_->AddDevice(id, type, std::string("/device/" + id));
[email protected]3c8bd112012-11-07 10:14:59171 }
172
173 void RemoveDevice(const std::string& id) {
[email protected]3c8bd112012-11-07 10:14:59174 device_test_->RemoveDevice(id);
175 }
176
177 void AddService(const std::string& type,
178 const std::string& id,
179 const std::string& state,
180 bool add_to_watch_list) {
181 ASSERT_TRUE(IsValidType(type));
[email protected]fde8b322013-02-28 17:44:24182 service_test_->AddService(id, id, type, state, add_to_watch_list);
[email protected]3c8bd112012-11-07 10:14:59183 }
184
185 void RemoveService(const std::string& id) {
[email protected]3c8bd112012-11-07 10:14:59186 service_test_->RemoveService(id);
187 }
188
189 // Call this after any initial Shill client setup
190 void SetupShillPropertyHandler() {
[email protected]1c86dbf2013-03-06 17:42:26191 SetupDefaultShillState();
[email protected]3c8bd112012-11-07 10:14:59192 listener_.reset(new TestListener);
193 shill_property_handler_.reset(
194 new internal::ShillPropertyHandler(listener_.get()));
195 shill_property_handler_->Init();
196 }
197
198 bool IsValidType(const std::string& type) {
199 return (type == flimflam::kTypeEthernet ||
200 type == flimflam::kTypeWifi ||
201 type == flimflam::kTypeWimax ||
202 type == flimflam::kTypeBluetooth ||
203 type == flimflam::kTypeCellular ||
204 type == flimflam::kTypeVPN);
205 }
206
207 protected:
[email protected]1c86dbf2013-03-06 17:42:26208 void SetupDefaultShillState() {
209 message_loop_.RunUntilIdle(); // Process any pending updates
210 device_test_->ClearDevices();
211 AddDevice(flimflam::kTypeWifi, "stub_wifi_device1");
212 AddDevice(flimflam::kTypeCellular, "stub_cellular_device1");
213 service_test_->ClearServices();
214 const bool add_to_watchlist = true;
215 AddService(flimflam::kTypeEthernet, "stub_ethernet",
216 flimflam::kStateOnline, add_to_watchlist);
217 AddService(flimflam::kTypeWifi, "stub_wifi1",
218 flimflam::kStateOnline, add_to_watchlist);
219 AddService(flimflam::kTypeWifi, "stub_wifi2",
220 flimflam::kStateIdle, add_to_watchlist);
221 AddService(flimflam::kTypeCellular, "stub_cellular1",
222 flimflam::kStateIdle, add_to_watchlist);
223 }
224
[email protected]3c8bd112012-11-07 10:14:59225 MessageLoopForUI message_loop_;
226 scoped_ptr<TestListener> listener_;
227 scoped_ptr<internal::ShillPropertyHandler> shill_property_handler_;
228 ShillManagerClient::TestInterface* manager_test_;
229 ShillDeviceClient::TestInterface* device_test_;
230 ShillServiceClient::TestInterface* service_test_;
231
232 private:
233 DISALLOW_COPY_AND_ASSIGN(ShillPropertyHandlerTest);
234};
235
236TEST_F(ShillPropertyHandlerTest, ShillPropertyHandlerStub) {
237 SetupShillPropertyHandler();
238 message_loop_.RunUntilIdle();
239 EXPECT_EQ(1, listener_->manager_updates());
[email protected]b16d79d72013-02-07 08:14:46240 EXPECT_TRUE(shill_property_handler_->TechnologyAvailable(
241 flimflam::kTypeWifi));
242 EXPECT_TRUE(shill_property_handler_->TechnologyEnabled(
243 flimflam::kTypeWifi));
[email protected]3c8bd112012-11-07 10:14:59244 const size_t kNumShillManagerClientStubImplDevices = 2;
245 EXPECT_EQ(kNumShillManagerClientStubImplDevices,
246 listener_->entries(flimflam::kDevicesProperty).size());
247 const size_t kNumShillManagerClientStubImplServices = 4;
248 EXPECT_EQ(kNumShillManagerClientStubImplServices,
249 listener_->entries(flimflam::kServicesProperty).size());
250
251 EXPECT_EQ(0, listener_->errors());
252}
253
254TEST_F(ShillPropertyHandlerTest, ShillPropertyHandlerTechnologyChanged) {
[email protected]3c8bd112012-11-07 10:14:59255 SetupShillPropertyHandler();
256 message_loop_.RunUntilIdle();
257 EXPECT_EQ(1, listener_->manager_updates());
258 // Add a disabled technology.
259 manager_test_->AddTechnology(flimflam::kTypeWimax, false);
260 message_loop_.RunUntilIdle();
261 EXPECT_EQ(2, listener_->manager_updates());
[email protected]b16d79d72013-02-07 08:14:46262 EXPECT_TRUE(shill_property_handler_->TechnologyAvailable(
263 flimflam::kTypeWimax));
264 EXPECT_FALSE(shill_property_handler_->TechnologyEnabled(
265 flimflam::kTypeWimax));
266
[email protected]3c8bd112012-11-07 10:14:59267 // Enable the technology.
268 DBusThreadManager::Get()->GetShillManagerClient()->EnableTechnology(
269 flimflam::kTypeWimax,
270 base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
271 message_loop_.RunUntilIdle();
272 EXPECT_EQ(3, listener_->manager_updates());
[email protected]b16d79d72013-02-07 08:14:46273 EXPECT_TRUE(shill_property_handler_->TechnologyEnabled(
274 flimflam::kTypeWimax));
[email protected]3c8bd112012-11-07 10:14:59275
276 EXPECT_EQ(0, listener_->errors());
277}
278
279TEST_F(ShillPropertyHandlerTest, ShillPropertyHandlerDevicePropertyChanged) {
[email protected]3c8bd112012-11-07 10:14:59280 SetupShillPropertyHandler();
281 message_loop_.RunUntilIdle();
282 EXPECT_EQ(1, listener_->manager_updates());
283 EXPECT_EQ(1, listener_->list_updates(flimflam::kDevicesProperty));
284 const size_t kNumShillManagerClientStubImplDevices = 2;
285 EXPECT_EQ(kNumShillManagerClientStubImplDevices,
286 listener_->entries(flimflam::kDevicesProperty).size());
287 // Add a device.
288 const std::string kTestDevicePath("test_wifi_device1");
289 AddDevice(flimflam::kTypeWifi, kTestDevicePath);
290 message_loop_.RunUntilIdle();
291 EXPECT_EQ(1, listener_->manager_updates()); // No new manager updates.
292 EXPECT_EQ(2, listener_->list_updates(flimflam::kDevicesProperty));
293 EXPECT_EQ(kNumShillManagerClientStubImplDevices + 1,
294 listener_->entries(flimflam::kDevicesProperty).size());
295 // Device changes are not observed.
296 // Remove a device
297 RemoveDevice(kTestDevicePath);
298 message_loop_.RunUntilIdle();
299 EXPECT_EQ(3, listener_->list_updates(flimflam::kDevicesProperty));
300 EXPECT_EQ(kNumShillManagerClientStubImplDevices,
301 listener_->entries(flimflam::kDevicesProperty).size());
302
303 EXPECT_EQ(0, listener_->errors());
304}
305
306TEST_F(ShillPropertyHandlerTest, ShillPropertyHandlerServicePropertyChanged) {
[email protected]3c8bd112012-11-07 10:14:59307 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());
314
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.
[email protected]b16d79d72013-02-07 08:14:46321 // Only watched services trigger a service list update.
322 EXPECT_EQ(1, listener_->list_updates(flimflam::kServicesProperty));
[email protected]3c8bd112012-11-07 10:14:59323 EXPECT_EQ(kNumShillManagerClientStubImplServices + 1,
324 listener_->entries(flimflam::kServicesProperty).size());
325 // Change a property.
326 base::FundamentalValue scan_interval(3);
327 DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
328 dbus::ObjectPath(kTestServicePath),
329 flimflam::kScanIntervalProperty,
330 scan_interval,
331 base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
332 message_loop_.RunUntilIdle();
333 // Property change should NOT trigger an update.
334 EXPECT_EQ(0, listener_->
335 property_updates(flimflam::kServicesProperty)[kTestServicePath]);
336
337 // Add the existing service to the watch list.
338 AddService(flimflam::kTypeWifi, kTestServicePath,
339 flimflam::kStateIdle, true);
340 message_loop_.RunUntilIdle();
[email protected]fa6797e2012-11-28 15:15:44341 // Service list update should be received when watch list changes.
[email protected]b16d79d72013-02-07 08:14:46342 EXPECT_EQ(2, listener_->list_updates(flimflam::kServicesProperty));
[email protected]fa6797e2012-11-28 15:15:44343 // Number of services shouldn't change.
[email protected]3c8bd112012-11-07 10:14:59344 EXPECT_EQ(kNumShillManagerClientStubImplServices + 1,
345 listener_->entries(flimflam::kServicesProperty).size());
[email protected]fa6797e2012-11-28 15:15:44346 // Property update should be received when watched service is added.
347 EXPECT_EQ(1, listener_->
348 property_updates(flimflam::kServicesProperty)[kTestServicePath]);
349
[email protected]3c8bd112012-11-07 10:14:59350 // Change a property.
351 DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
352 dbus::ObjectPath(kTestServicePath),
353 flimflam::kScanIntervalProperty,
354 scan_interval,
355 base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
356 message_loop_.RunUntilIdle();
[email protected]fa6797e2012-11-28 15:15:44357 // Property change should trigger another update.
358 EXPECT_EQ(2, listener_->
[email protected]3c8bd112012-11-07 10:14:59359 property_updates(flimflam::kServicesProperty)[kTestServicePath]);
360
361 // Remove a service
362 RemoveService(kTestServicePath);
363 message_loop_.RunUntilIdle();
[email protected]b16d79d72013-02-07 08:14:46364 EXPECT_EQ(3, listener_->list_updates(flimflam::kServicesProperty));
[email protected]3c8bd112012-11-07 10:14:59365 EXPECT_EQ(kNumShillManagerClientStubImplServices,
366 listener_->entries(flimflam::kServicesProperty).size());
367
368 EXPECT_EQ(0, listener_->errors());
369}
370
371// TODO(stevenjb): Test IP Configs.
372
373} // namespace chromeos