- add sources.
[platform/framework/web/crosswalk.git] / src / chromeos / network / shill_property_handler_unittest.cc
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.
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/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_ipconfig_client.h"
18 #include "chromeos/dbus/shill_manager_client.h"
19 #include "chromeos/dbus/shill_profile_client.h"
20 #include "chromeos/dbus/shill_service_client.h"
21 #include "dbus/object_path.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "third_party/cros_system_api/dbus/service_constants.h"
24
25 namespace chromeos {
26
27 namespace {
28
29 void DoNothingWithCallStatus(DBusMethodCallStatus call_status) {
30 }
31
32 void ErrorCallbackFunction(const std::string& error_name,
33                            const std::string& error_message) {
34   LOG(ERROR) << "Shill Error: " << error_name << " : " << error_message;
35 }
36
37 class TestListener : public internal::ShillPropertyHandler::Listener {
38  public:
39   TestListener() : technology_list_updates_(0),
40                    errors_(0) {
41   }
42
43   virtual void UpdateManagedList(ManagedState::ManagedType type,
44                                  const base::ListValue& entries) OVERRIDE {
45     UpdateEntries(GetTypeString(type), entries);
46   }
47
48   virtual void UpdateManagedStateProperties(
49       ManagedState::ManagedType type,
50       const std::string& path,
51       const base::DictionaryValue& properties) OVERRIDE {
52     AddInitialPropertyUpdate(GetTypeString(type), path);
53   }
54
55   virtual void ProfileListChanged() OVERRIDE {
56   }
57
58   virtual void UpdateNetworkServiceProperty(
59       const std::string& service_path,
60       const std::string& key,
61       const base::Value& value) OVERRIDE {
62     AddPropertyUpdate(shill::kServicesProperty, service_path);
63   }
64
65   virtual void UpdateDeviceProperty(
66       const std::string& device_path,
67       const std::string& key,
68       const base::Value& value) OVERRIDE {
69     AddPropertyUpdate(shill::kDevicesProperty, device_path);
70   }
71
72   virtual void TechnologyListChanged() OVERRIDE {
73     ++technology_list_updates_;
74   }
75
76   virtual void CheckPortalListChanged(
77       const std::string& check_portal_list) OVERRIDE {
78   }
79
80   virtual void ManagedStateListChanged(
81       ManagedState::ManagedType type) OVERRIDE {
82     AddStateListUpdate(GetTypeString(type));
83   }
84
85   std::vector<std::string>& entries(const std::string& type) {
86     return entries_[type];
87   }
88   std::map<std::string, int>& property_updates(const std::string& type) {
89     return property_updates_[type];
90   }
91   std::map<std::string, int>& initial_property_updates(
92       const std::string& type) {
93     return initial_property_updates_[type];
94   }
95   int list_updates(const std::string& type) { return list_updates_[type]; }
96   int technology_list_updates() { return technology_list_updates_; }
97   int errors() { return errors_; }
98
99  private:
100   std::string GetTypeString(ManagedState::ManagedType type) {
101     if (type == ManagedState::MANAGED_TYPE_NETWORK) {
102       return shill::kServicesProperty;
103     } else if (type == ManagedState::MANAGED_TYPE_FAVORITE) {
104       return shill::kServiceCompleteListProperty;
105     } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
106       return shill::kDevicesProperty;
107     }
108     LOG(ERROR) << "UpdateManagedList called with unrecognized type: " << type;
109     ++errors_;
110     return std::string();
111   }
112
113   void UpdateEntries(const std::string& type, const base::ListValue& entries) {
114     if (type.empty())
115       return;
116     entries_[type].clear();
117     for (base::ListValue::const_iterator iter = entries.begin();
118          iter != entries.end(); ++iter) {
119       std::string path;
120       if ((*iter)->GetAsString(&path))
121         entries_[type].push_back(path);
122     }
123   }
124
125   void AddPropertyUpdate(const std::string& type, const std::string& path) {
126     if (type.empty())
127       return;
128     property_updates(type)[path] += 1;
129   }
130
131   void AddInitialPropertyUpdate(const std::string& type,
132                                 const std::string& path) {
133     if (type.empty())
134       return;
135     initial_property_updates(type)[path] += 1;
136   }
137
138   void AddStateListUpdate(const std::string& type) {
139     if (type.empty())
140       return;
141     list_updates_[type] += 1;
142   }
143
144   // Map of list-type -> paths
145   std::map<std::string, std::vector<std::string> > entries_;
146   // Map of list-type -> map of paths -> update counts
147   std::map<std::string, std::map<std::string, int> > property_updates_;
148   std::map<std::string, std::map<std::string, int> > initial_property_updates_;
149   // Map of list-type -> list update counts
150   std::map<std::string, int > list_updates_;
151   int technology_list_updates_;
152   int errors_;
153 };
154
155 }  // namespace
156
157 class ShillPropertyHandlerTest : public testing::Test {
158  public:
159   ShillPropertyHandlerTest()
160       : manager_test_(NULL),
161         device_test_(NULL),
162         service_test_(NULL),
163         profile_test_(NULL) {
164   }
165   virtual ~ShillPropertyHandlerTest() {
166   }
167
168   virtual void SetUp() OVERRIDE {
169     // Initialize DBusThreadManager with a stub implementation.
170     DBusThreadManager::InitializeWithStub();
171     // Get the test interface for manager / device / service and clear the
172     // default stub properties.
173     manager_test_ =
174         DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface();
175     ASSERT_TRUE(manager_test_);
176     device_test_ =
177         DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface();
178     ASSERT_TRUE(device_test_);
179     service_test_ =
180         DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
181     ASSERT_TRUE(service_test_);
182     profile_test_ =
183         DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface();
184     ASSERT_TRUE(profile_test_);
185     SetupShillPropertyHandler();
186     message_loop_.RunUntilIdle();
187   }
188
189   virtual void TearDown() OVERRIDE {
190     shill_property_handler_.reset();
191     listener_.reset();
192     DBusThreadManager::Shutdown();
193   }
194
195   void AddDevice(const std::string& type, const std::string& id) {
196     ASSERT_TRUE(IsValidType(type));
197     device_test_->AddDevice(id, type, std::string("/device/" + id));
198   }
199
200   void RemoveDevice(const std::string& id) {
201     device_test_->RemoveDevice(id);
202   }
203
204   void AddService(const std::string& type,
205                   const std::string& id,
206                   const std::string& state,
207                   bool add_to_watch_list) {
208     ASSERT_TRUE(IsValidType(type));
209     service_test_->AddService(id, id, type, state,
210                               true /* visible */, add_to_watch_list);
211   }
212
213   void AddServiceWithIPConfig(const std::string& type,
214                               const std::string& id,
215                               const std::string& state,
216                               const std::string& ipconfig_path,
217                               bool add_to_watch_list) {
218     ASSERT_TRUE(IsValidType(type));
219     service_test_->AddServiceWithIPConfig(id, id, type, state,
220                                           ipconfig_path,
221                                           true /* visible */,
222                                           add_to_watch_list);
223   }
224
225   void AddServiceToProfile(const std::string& type,
226                            const std::string& id,
227                            bool visible) {
228     service_test_->AddService(id, id, type, shill::kStateIdle,
229                               visible, false /* watch */);
230     std::vector<std::string> profiles;
231     profile_test_->GetProfilePaths(&profiles);
232     ASSERT_TRUE(profiles.size() > 0);
233     base::DictionaryValue properties;  // Empty entry
234     profile_test_->AddService(profiles[0], id);
235   }
236
237   void RemoveService(const std::string& id) {
238     service_test_->RemoveService(id);
239   }
240
241   // Call this after any initial Shill client setup
242   void SetupShillPropertyHandler() {
243     SetupDefaultShillState();
244     listener_.reset(new TestListener);
245     shill_property_handler_.reset(
246         new internal::ShillPropertyHandler(listener_.get()));
247     shill_property_handler_->Init();
248   }
249
250   bool IsValidType(const std::string& type) {
251     return (type == shill::kTypeEthernet ||
252             type == shill::kTypeEthernetEap ||
253             type == shill::kTypeWifi ||
254             type == shill::kTypeWimax ||
255             type == shill::kTypeBluetooth ||
256             type == shill::kTypeCellular ||
257             type == shill::kTypeVPN);
258   }
259
260  protected:
261   void SetupDefaultShillState() {
262     message_loop_.RunUntilIdle();  // Process any pending updates
263     device_test_->ClearDevices();
264     AddDevice(shill::kTypeWifi, "stub_wifi_device1");
265     AddDevice(shill::kTypeCellular, "stub_cellular_device1");
266     service_test_->ClearServices();
267     const bool add_to_watchlist = true;
268     AddService(shill::kTypeEthernet, "stub_ethernet",
269                shill::kStateOnline, add_to_watchlist);
270     AddService(shill::kTypeWifi, "stub_wifi1",
271                shill::kStateOnline, add_to_watchlist);
272     AddService(shill::kTypeWifi, "stub_wifi2",
273                shill::kStateIdle, add_to_watchlist);
274     AddService(shill::kTypeCellular, "stub_cellular1",
275                shill::kStateIdle, add_to_watchlist);
276   }
277
278   base::MessageLoopForUI message_loop_;
279   scoped_ptr<TestListener> listener_;
280   scoped_ptr<internal::ShillPropertyHandler> shill_property_handler_;
281   ShillManagerClient::TestInterface* manager_test_;
282   ShillDeviceClient::TestInterface* device_test_;
283   ShillServiceClient::TestInterface* service_test_;
284   ShillProfileClient::TestInterface* profile_test_;
285
286  private:
287   DISALLOW_COPY_AND_ASSIGN(ShillPropertyHandlerTest);
288 };
289
290 TEST_F(ShillPropertyHandlerTest, ShillPropertyHandlerStub) {
291   EXPECT_TRUE(shill_property_handler_->IsTechnologyAvailable(shill::kTypeWifi));
292   EXPECT_TRUE(shill_property_handler_->IsTechnologyEnabled(shill::kTypeWifi));
293   const size_t kNumShillManagerClientStubImplDevices = 2;
294   EXPECT_EQ(kNumShillManagerClientStubImplDevices,
295             listener_->entries(shill::kDevicesProperty).size());
296   const size_t kNumShillManagerClientStubImplServices = 4;
297   EXPECT_EQ(kNumShillManagerClientStubImplServices,
298             listener_->entries(shill::kServicesProperty).size());
299
300   EXPECT_EQ(0, listener_->errors());
301 }
302
303 TEST_F(ShillPropertyHandlerTest, ShillPropertyHandlerTechnologyChanged) {
304   const int initial_technology_updates = 2;  // Available and Enabled lists
305   EXPECT_EQ(initial_technology_updates, listener_->technology_list_updates());
306
307   // Remove a technology. Updates both the Available and Enabled lists.
308   manager_test_->RemoveTechnology(shill::kTypeWimax);
309   message_loop_.RunUntilIdle();
310   EXPECT_EQ(initial_technology_updates + 2,
311             listener_->technology_list_updates());
312
313   // Add a disabled technology.
314   manager_test_->AddTechnology(shill::kTypeWimax, false);
315   message_loop_.RunUntilIdle();
316   EXPECT_EQ(initial_technology_updates + 3,
317             listener_->technology_list_updates());
318   EXPECT_TRUE(shill_property_handler_->IsTechnologyAvailable(
319       shill::kTypeWimax));
320   EXPECT_FALSE(shill_property_handler_->IsTechnologyEnabled(shill::kTypeWimax));
321
322   // Enable the technology.
323   DBusThreadManager::Get()->GetShillManagerClient()->EnableTechnology(
324       shill::kTypeWimax,
325       base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
326   message_loop_.RunUntilIdle();
327   EXPECT_EQ(initial_technology_updates + 4,
328             listener_->technology_list_updates());
329   EXPECT_TRUE(shill_property_handler_->IsTechnologyEnabled(shill::kTypeWimax));
330
331   EXPECT_EQ(0, listener_->errors());
332 }
333
334 TEST_F(ShillPropertyHandlerTest, ShillPropertyHandlerDevicePropertyChanged) {
335   EXPECT_EQ(1, listener_->list_updates(shill::kDevicesProperty));
336   const size_t kNumShillManagerClientStubImplDevices = 2;
337   EXPECT_EQ(kNumShillManagerClientStubImplDevices,
338             listener_->entries(shill::kDevicesProperty).size());
339   // Add a device.
340   const std::string kTestDevicePath("test_wifi_device1");
341   AddDevice(shill::kTypeWifi, kTestDevicePath);
342   message_loop_.RunUntilIdle();
343   EXPECT_EQ(2, listener_->list_updates(shill::kDevicesProperty));
344   EXPECT_EQ(kNumShillManagerClientStubImplDevices + 1,
345             listener_->entries(shill::kDevicesProperty).size());
346   // Device changes are not observed.
347   // Remove a device
348   RemoveDevice(kTestDevicePath);
349   message_loop_.RunUntilIdle();
350   EXPECT_EQ(3, listener_->list_updates(shill::kDevicesProperty));
351   EXPECT_EQ(kNumShillManagerClientStubImplDevices,
352             listener_->entries(shill::kDevicesProperty).size());
353
354   EXPECT_EQ(0, listener_->errors());
355 }
356
357 TEST_F(ShillPropertyHandlerTest, ShillPropertyHandlerServicePropertyChanged) {
358   EXPECT_EQ(1, listener_->list_updates(shill::kServicesProperty));
359   const size_t kNumShillManagerClientStubImplServices = 4;
360   EXPECT_EQ(kNumShillManagerClientStubImplServices,
361             listener_->entries(shill::kServicesProperty).size());
362
363   // Add an unwatched service.
364   const std::string kTestServicePath("test_wifi_service1");
365   AddService(shill::kTypeWifi, kTestServicePath, shill::kStateIdle, false);
366   message_loop_.RunUntilIdle();
367   // Watched and unwatched services trigger a service list update.
368   EXPECT_EQ(2, listener_->list_updates(shill::kServicesProperty));
369   EXPECT_EQ(kNumShillManagerClientStubImplServices + 1,
370             listener_->entries(shill::kServicesProperty).size());
371   // Service receives an initial property update.
372   EXPECT_EQ(1, listener_->initial_property_updates(
373       shill::kServicesProperty)[kTestServicePath]);
374   // Change a property.
375   base::FundamentalValue scan_interval(3);
376   DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
377       dbus::ObjectPath(kTestServicePath),
378       shill::kScanIntervalProperty,
379       scan_interval,
380       base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
381   message_loop_.RunUntilIdle();
382   // Property change triggers an update.
383   EXPECT_EQ(1, listener_->property_updates(
384       shill::kServicesProperty)[kTestServicePath]);
385
386   // Add the existing service to the watch list.
387   AddService(shill::kTypeWifi, kTestServicePath, shill::kStateIdle, true);
388   message_loop_.RunUntilIdle();
389   // Service list update should be received when watch list changes.
390   EXPECT_EQ(2, listener_->list_updates(shill::kServicesProperty));
391   // Number of services shouldn't change.
392   EXPECT_EQ(kNumShillManagerClientStubImplServices + 1,
393             listener_->entries(shill::kServicesProperty).size());
394
395   // Change a property.
396   DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
397       dbus::ObjectPath(kTestServicePath),
398       shill::kScanIntervalProperty,
399       scan_interval,
400       base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
401   message_loop_.RunUntilIdle();
402   // Property change should trigger another update.
403   EXPECT_EQ(2, listener_->property_updates(
404       shill::kServicesProperty)[kTestServicePath]);
405
406   // Remove a service
407   RemoveService(kTestServicePath);
408   message_loop_.RunUntilIdle();
409   EXPECT_EQ(3, listener_->list_updates(shill::kServicesProperty));
410   EXPECT_EQ(kNumShillManagerClientStubImplServices,
411             listener_->entries(shill::kServicesProperty).size());
412
413   EXPECT_EQ(0, listener_->errors());
414 }
415
416 TEST_F(ShillPropertyHandlerTest, ShillPropertyHandlerIPConfigPropertyChanged) {
417   // Set the properties for an IP Config object.
418   const std::string kTestIPConfigPath("test_ip_config_path");
419
420   base::StringValue ip_address("192.168.1.1");
421   DBusThreadManager::Get()->GetShillIPConfigClient()->SetProperty(
422       dbus::ObjectPath(kTestIPConfigPath),
423       shill::kAddressProperty, ip_address,
424       base::Bind(&DoNothingWithCallStatus));
425   base::ListValue dns_servers;
426   dns_servers.Append(base::Value::CreateStringValue("192.168.1.100"));
427   dns_servers.Append(base::Value::CreateStringValue("192.168.1.101"));
428   DBusThreadManager::Get()->GetShillIPConfigClient()->SetProperty(
429       dbus::ObjectPath(kTestIPConfigPath),
430       shill::kNameServersProperty, dns_servers,
431       base::Bind(&DoNothingWithCallStatus));
432   base::FundamentalValue prefixlen(8);
433   DBusThreadManager::Get()->GetShillIPConfigClient()->SetProperty(
434       dbus::ObjectPath(kTestIPConfigPath),
435       shill::kPrefixlenProperty, prefixlen,
436       base::Bind(&DoNothingWithCallStatus));
437   base::StringValue gateway("192.0.0.1");
438   DBusThreadManager::Get()->GetShillIPConfigClient()->SetProperty(
439       dbus::ObjectPath(kTestIPConfigPath),
440       shill::kGatewayProperty, gateway,
441       base::Bind(&DoNothingWithCallStatus));
442   message_loop_.RunUntilIdle();
443
444   // Add a service with an empty ipconfig and then update
445   // its ipconfig property.
446   const std::string kTestServicePath1("test_wifi_service1");
447   AddService(shill::kTypeWifi, kTestServicePath1, shill::kStateIdle, true);
448   message_loop_.RunUntilIdle();
449   // This is the initial property update.
450   EXPECT_EQ(1, listener_->initial_property_updates(
451       shill::kServicesProperty)[kTestServicePath1]);
452   DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
453       dbus::ObjectPath(kTestServicePath1),
454       shill::kIPConfigProperty,
455       base::StringValue(kTestIPConfigPath),
456       base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
457   message_loop_.RunUntilIdle();
458   // IPConfig property change on the service should trigger property updates for
459   // IP Address, DNS, prefixlen, and gateway.
460   EXPECT_EQ(4, listener_->property_updates(
461       shill::kServicesProperty)[kTestServicePath1]);
462
463   // Now, Add a new watched service with the IPConfig already set.
464   const std::string kTestServicePath2("test_wifi_service2");
465   AddServiceWithIPConfig(shill::kTypeWifi, kTestServicePath2,
466                          shill::kStateIdle, kTestIPConfigPath, true);
467   message_loop_.RunUntilIdle();
468   // A watched service with the IPConfig property already set must trigger
469   // property updates for IP Address, DNS, prefixlen, and gateway when added.
470   EXPECT_EQ(4, listener_->property_updates(
471       shill::kServicesProperty)[kTestServicePath2]);
472 }
473
474 TEST_F(ShillPropertyHandlerTest, ShillPropertyHandlerServiceCompleteList) {
475   // Initial list updates.
476   EXPECT_EQ(1, listener_->list_updates(shill::kServicesProperty));
477   EXPECT_EQ(1, listener_->list_updates(shill::kServiceCompleteListProperty));
478
479   // Add a new entry to the profile only; should trigger a single list update
480   // for both Services and ServiceCompleteList, and a single property update
481   // for ServiceCompleteList.
482   const std::string kTestServicePath1("stub_wifi_profile_only1");
483   AddServiceToProfile(shill::kTypeWifi, kTestServicePath1, false);
484   shill_property_handler_->UpdateManagerProperties();
485   message_loop_.RunUntilIdle();
486   EXPECT_EQ(2, listener_->list_updates(shill::kServicesProperty));
487   EXPECT_EQ(2, listener_->list_updates(shill::kServiceCompleteListProperty));
488   EXPECT_EQ(0, listener_->initial_property_updates(
489       shill::kServicesProperty)[kTestServicePath1]);
490   EXPECT_EQ(1, listener_->initial_property_updates(
491       shill::kServiceCompleteListProperty)[kTestServicePath1]);
492   EXPECT_EQ(0, listener_->property_updates(
493       shill::kServicesProperty)[kTestServicePath1]);
494   EXPECT_EQ(0, listener_->property_updates(
495       shill::kServiceCompleteListProperty)[kTestServicePath1]);
496
497   // Add a new entry to the services and the profile; should also trigger a
498   // single list update for both Services and ServiceCompleteList, and should
499   // trigger tow property updates for Services (one when the Profile propety
500   // changes, and one for the Request) and one ServiceCompleteList change for
501   // the Request.
502   const std::string kTestServicePath2("stub_wifi_profile_only2");
503   AddServiceToProfile(shill::kTypeWifi, kTestServicePath2, true);
504   shill_property_handler_->UpdateManagerProperties();
505   message_loop_.RunUntilIdle();
506   EXPECT_EQ(3, listener_->list_updates(shill::kServicesProperty));
507   EXPECT_EQ(3, listener_->list_updates(shill::kServiceCompleteListProperty));
508   EXPECT_EQ(1, listener_->initial_property_updates(
509       shill::kServicesProperty)[kTestServicePath2]);
510   EXPECT_EQ(1, listener_->initial_property_updates(
511       shill::kServiceCompleteListProperty)[kTestServicePath2]);
512   // Expect one property update for the Profile property of the Network.
513   EXPECT_EQ(1, listener_->property_updates(
514       shill::kServicesProperty)[kTestServicePath2]);
515   EXPECT_EQ(0, listener_->property_updates(
516       shill::kServiceCompleteListProperty)[kTestServicePath2]);
517
518   // Change a property of a Network in a Profile.
519   base::FundamentalValue scan_interval(3);
520   DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
521       dbus::ObjectPath(kTestServicePath2),
522       shill::kScanIntervalProperty,
523       scan_interval,
524       base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
525   message_loop_.RunUntilIdle();
526   // Property change should trigger an update for the Network only; no
527   // property updates pushed by Shill affect Favorites.
528   EXPECT_EQ(2, listener_->property_updates(
529       shill::kServicesProperty)[kTestServicePath2]);
530   EXPECT_EQ(0, listener_->property_updates(
531       shill::kServiceCompleteListProperty)[kTestServicePath2]);
532 }
533
534 }  // namespace chromeos