• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/network_state_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_manager_client.h"
18 #include "chromeos/dbus/shill_profile_client.h"
19 #include "chromeos/dbus/shill_service_client.h"
20 #include "chromeos/network/network_state.h"
21 #include "chromeos/network/network_state_handler_observer.h"
22 #include "chromeos/network/shill_property_util.h"
23 #include "dbus/object_path.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "third_party/cros_system_api/dbus/service_constants.h"
26 
27 namespace {
28 
ErrorCallbackFunction(const std::string & error_name,const std::string & error_message)29 void ErrorCallbackFunction(const std::string& error_name,
30                            const std::string& error_message) {
31   LOG(ERROR) << "Shill Error: " << error_name << " : " << error_message;
32 }
33 
34 const std::string kShillManagerClientStubDefaultService = "eth1";
35 const std::string kShillManagerClientStubDefaultWireless = "wifi1";
36 const std::string kShillManagerClientStubWireless2 = "wifi2";
37 const std::string kShillManagerClientStubCellular = "cellular1";
38 
39 using chromeos::NetworkState;
40 using chromeos::NetworkStateHandler;
41 
42 class TestObserver : public chromeos::NetworkStateHandlerObserver {
43  public:
TestObserver(NetworkStateHandler * handler)44   explicit TestObserver(NetworkStateHandler* handler)
45       : handler_(handler),
46         device_list_changed_count_(0),
47         network_count_(0),
48         default_network_change_count_(0),
49         favorite_count_(0) {
50   }
51 
~TestObserver()52   virtual ~TestObserver() {
53   }
54 
DeviceListChanged()55   virtual void DeviceListChanged() OVERRIDE {
56     ++device_list_changed_count_;
57   }
58 
NetworkListChanged()59   virtual void NetworkListChanged() OVERRIDE {
60     NetworkStateHandler::NetworkStateList networks;
61     handler_->GetNetworkList(&networks);
62     network_count_ = networks.size();
63     if (network_count_ == 0) {
64       default_network_ = "";
65       default_network_connection_state_ = "";
66     }
67     NetworkStateHandler::FavoriteStateList favorites;
68     handler_->GetFavoriteList(&favorites);
69     favorite_count_ = favorites.size();
70   }
71 
DefaultNetworkChanged(const NetworkState * network)72   virtual void DefaultNetworkChanged(const NetworkState* network) OVERRIDE {
73     ++default_network_change_count_;
74     default_network_ = network ? network->path() : "";
75     default_network_connection_state_ =
76         network ?  network->connection_state() : "";
77   }
78 
NetworkConnectionStateChanged(const NetworkState * network)79   virtual void NetworkConnectionStateChanged(
80       const NetworkState* network) OVERRIDE {
81     network_connection_state_[network->path()] = network->connection_state();
82     connection_state_changes_[network->path()]++;
83   }
84 
NetworkPropertiesUpdated(const NetworkState * network)85   virtual void NetworkPropertiesUpdated(const NetworkState* network) OVERRIDE {
86     DCHECK(network);
87     property_updates_[network->path()]++;
88   }
89 
device_list_changed_count()90   size_t device_list_changed_count() { return device_list_changed_count_; }
network_count()91   size_t network_count() { return network_count_; }
default_network_change_count()92   size_t default_network_change_count() {
93     return default_network_change_count_;
94   }
default_network()95   std::string default_network() { return default_network_; }
default_network_connection_state()96   std::string default_network_connection_state() {
97     return default_network_connection_state_;
98   }
favorite_count()99   size_t favorite_count() { return favorite_count_; }
100 
PropertyUpdatesForService(const std::string & service_path)101   int PropertyUpdatesForService(const std::string& service_path) {
102     return property_updates_[service_path];
103   }
104 
ConnectionStateChangesForService(const std::string & service_path)105   int ConnectionStateChangesForService(const std::string& service_path) {
106     return connection_state_changes_[service_path];
107   }
108 
NetworkConnectionStateForService(const std::string & service_path)109   std::string NetworkConnectionStateForService(
110       const std::string& service_path) {
111     return network_connection_state_[service_path];
112   }
113 
114  private:
115   NetworkStateHandler* handler_;
116   size_t device_list_changed_count_;
117   size_t network_count_;
118   size_t default_network_change_count_;
119   std::string default_network_;
120   std::string default_network_connection_state_;
121   size_t favorite_count_;
122   std::map<std::string, int> property_updates_;
123   std::map<std::string, int> connection_state_changes_;
124   std::map<std::string, std::string> network_connection_state_;
125 
126   DISALLOW_COPY_AND_ASSIGN(TestObserver);
127 };
128 
129 }  // namespace
130 
131 namespace chromeos {
132 
133 class NetworkStateHandlerTest : public testing::Test {
134  public:
NetworkStateHandlerTest()135   NetworkStateHandlerTest() {}
~NetworkStateHandlerTest()136   virtual ~NetworkStateHandlerTest() {}
137 
SetUp()138   virtual void SetUp() OVERRIDE {
139     // Initialize DBusThreadManager with a stub implementation.
140     DBusThreadManager::InitializeWithStub();
141     SetupNetworkStateHandler();
142     message_loop_.RunUntilIdle();
143   }
144 
TearDown()145   virtual void TearDown() OVERRIDE {
146     network_state_handler_->RemoveObserver(test_observer_.get(), FROM_HERE);
147     test_observer_.reset();
148     network_state_handler_.reset();
149     DBusThreadManager::Shutdown();
150   }
151 
SetupNetworkStateHandler()152   void SetupNetworkStateHandler() {
153     SetupDefaultShillState();
154     network_state_handler_.reset(new NetworkStateHandler);
155     test_observer_.reset(new TestObserver(network_state_handler_.get()));
156     network_state_handler_->AddObserver(test_observer_.get(), FROM_HERE);
157     network_state_handler_->InitShillPropertyHandler();
158   }
159 
160  protected:
SetupDefaultShillState()161   void SetupDefaultShillState() {
162     message_loop_.RunUntilIdle();  // Process any pending updates
163     ShillDeviceClient::TestInterface* device_test =
164         DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface();
165     device_test->ClearDevices();
166     device_test->AddDevice("/device/stub_wifi_device1",
167                            shill::kTypeWifi, "stub_wifi_device1");
168     device_test->AddDevice("/device/stub_cellular_device1",
169                            shill::kTypeCellular, "stub_cellular_device1");
170 
171     ShillServiceClient::TestInterface* service_test =
172         DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
173     service_test->ClearServices();
174     const bool add_to_visible = true;
175     const bool add_to_watchlist = true;
176     service_test->AddService(kShillManagerClientStubDefaultService,
177                              kShillManagerClientStubDefaultService,
178                              shill::kTypeEthernet, shill::kStateOnline,
179                              add_to_visible, add_to_watchlist);
180     service_test->AddService(kShillManagerClientStubDefaultWireless,
181                              kShillManagerClientStubDefaultWireless,
182                              shill::kTypeWifi, shill::kStateOnline,
183                              add_to_visible, add_to_watchlist);
184     service_test->AddService(kShillManagerClientStubWireless2,
185                              kShillManagerClientStubWireless2,
186                              shill::kTypeWifi, shill::kStateIdle,
187                              add_to_visible, add_to_watchlist);
188     service_test->AddService(kShillManagerClientStubCellular,
189                              kShillManagerClientStubCellular,
190                              shill::kTypeCellular, shill::kStateIdle,
191                              add_to_visible, add_to_watchlist);
192   }
193 
194   base::MessageLoopForUI message_loop_;
195   scoped_ptr<NetworkStateHandler> network_state_handler_;
196   scoped_ptr<TestObserver> test_observer_;
197 
198  private:
199   DISALLOW_COPY_AND_ASSIGN(NetworkStateHandlerTest);
200 };
201 
TEST_F(NetworkStateHandlerTest,NetworkStateHandlerStub)202 TEST_F(NetworkStateHandlerTest, NetworkStateHandlerStub) {
203   // Ensure that the network list is the expected size.
204   const size_t kNumShillManagerClientStubImplServices = 4;
205   EXPECT_EQ(kNumShillManagerClientStubImplServices,
206             test_observer_->network_count());
207   // Ensure that the first stub network is the default network.
208   EXPECT_EQ(kShillManagerClientStubDefaultService,
209             test_observer_->default_network());
210   EXPECT_EQ(kShillManagerClientStubDefaultService,
211             network_state_handler_->ConnectedNetworkByType(
212                 NetworkTypePattern::Default())->path());
213   EXPECT_EQ(kShillManagerClientStubDefaultService,
214             network_state_handler_->ConnectedNetworkByType(
215                 NetworkTypePattern::Ethernet())->path());
216   EXPECT_EQ(kShillManagerClientStubDefaultWireless,
217             network_state_handler_->ConnectedNetworkByType(
218                 NetworkTypePattern::Wireless())->path());
219   EXPECT_EQ(kShillManagerClientStubCellular,
220             network_state_handler_->FirstNetworkByType(
221                 NetworkTypePattern::Mobile())->path());
222   EXPECT_EQ(
223       kShillManagerClientStubCellular,
224       network_state_handler_->FirstNetworkByType(NetworkTypePattern::Cellular())
225           ->path());
226   EXPECT_EQ(shill::kStateOnline,
227             test_observer_->default_network_connection_state());
228 }
229 
TEST_F(NetworkStateHandlerTest,TechnologyChanged)230 TEST_F(NetworkStateHandlerTest, TechnologyChanged) {
231   // There may be several manager changes during initialization.
232   size_t initial_changed_count = test_observer_->device_list_changed_count();
233   // Disable a technology.
234   network_state_handler_->SetTechnologyEnabled(
235       NetworkTypePattern::Wimax(), false, network_handler::ErrorCallback());
236   EXPECT_NE(
237       NetworkStateHandler::TECHNOLOGY_ENABLED,
238       network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
239   EXPECT_EQ(initial_changed_count + 1,
240             test_observer_->device_list_changed_count());
241   // Enable a technology.
242   network_state_handler_->SetTechnologyEnabled(
243       NetworkTypePattern::Wimax(), true, network_handler::ErrorCallback());
244   // The technology state should immediately change to ENABLING and we should
245   // receive a manager changed callback.
246   EXPECT_EQ(initial_changed_count + 2,
247             test_observer_->device_list_changed_count());
248   EXPECT_EQ(
249       NetworkStateHandler::TECHNOLOGY_ENABLING,
250       network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
251   message_loop_.RunUntilIdle();
252   // Ensure we receive 2 manager changed callbacks when the technology becomes
253   // avalable and enabled.
254   EXPECT_EQ(initial_changed_count + 4,
255             test_observer_->device_list_changed_count());
256   EXPECT_EQ(
257       NetworkStateHandler::TECHNOLOGY_ENABLED,
258       network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
259 }
260 
TEST_F(NetworkStateHandlerTest,TechnologyState)261 TEST_F(NetworkStateHandlerTest, TechnologyState) {
262   ShillManagerClient::TestInterface* manager_test =
263       DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface();
264   manager_test->RemoveTechnology(shill::kTypeWimax);
265   message_loop_.RunUntilIdle();
266   EXPECT_EQ(
267       NetworkStateHandler::TECHNOLOGY_UNAVAILABLE,
268       network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
269 
270   manager_test->AddTechnology(shill::kTypeWimax, false);
271   message_loop_.RunUntilIdle();
272   EXPECT_EQ(
273       NetworkStateHandler::TECHNOLOGY_AVAILABLE,
274       network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
275 
276   manager_test->SetTechnologyInitializing(shill::kTypeWimax, true);
277   message_loop_.RunUntilIdle();
278   EXPECT_EQ(
279       NetworkStateHandler::TECHNOLOGY_UNINITIALIZED,
280       network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
281 
282   manager_test->SetTechnologyInitializing(shill::kTypeWimax, false);
283   network_state_handler_->SetTechnologyEnabled(
284       NetworkTypePattern::Wimax(), true, network_handler::ErrorCallback());
285   message_loop_.RunUntilIdle();
286   EXPECT_EQ(
287       NetworkStateHandler::TECHNOLOGY_ENABLED,
288       network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
289 
290   manager_test->RemoveTechnology(shill::kTypeWimax);
291   message_loop_.RunUntilIdle();
292   EXPECT_EQ(
293       NetworkStateHandler::TECHNOLOGY_UNAVAILABLE,
294       network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
295 }
296 
TEST_F(NetworkStateHandlerTest,ServicePropertyChanged)297 TEST_F(NetworkStateHandlerTest, ServicePropertyChanged) {
298   // Set a service property.
299   const std::string eth1 = kShillManagerClientStubDefaultService;
300   EXPECT_EQ("", network_state_handler_->GetNetworkState(eth1)->security());
301   EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(eth1));
302   base::StringValue security_value("TestSecurity");
303   DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
304       dbus::ObjectPath(eth1),
305       shill::kSecurityProperty, security_value,
306       base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
307   message_loop_.RunUntilIdle();
308   EXPECT_EQ("TestSecurity",
309             network_state_handler_->GetNetworkState(eth1)->security());
310   EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(eth1));
311 
312   // Changing a service to the existing value should not trigger an update.
313   DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
314       dbus::ObjectPath(eth1),
315       shill::kSecurityProperty, security_value,
316       base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
317   message_loop_.RunUntilIdle();
318   EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(eth1));
319 }
320 
TEST_F(NetworkStateHandlerTest,FavoriteState)321 TEST_F(NetworkStateHandlerTest, FavoriteState) {
322   // Set the profile entry of a service
323   const std::string wifi1 = kShillManagerClientStubDefaultWireless;
324   ShillProfileClient::TestInterface* profile_test =
325       DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface();
326   EXPECT_TRUE(profile_test->AddService("/profile/default", wifi1));
327   message_loop_.RunUntilIdle();
328   network_state_handler_->UpdateManagerProperties();
329   message_loop_.RunUntilIdle();
330   EXPECT_EQ(1u, test_observer_->favorite_count());
331 }
332 
TEST_F(NetworkStateHandlerTest,NetworkConnectionStateChanged)333 TEST_F(NetworkStateHandlerTest, NetworkConnectionStateChanged) {
334   // Change a network state.
335   ShillServiceClient::TestInterface* service_test =
336       DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
337   const std::string eth1 = kShillManagerClientStubDefaultService;
338   base::StringValue connection_state_idle_value(shill::kStateIdle);
339   service_test->SetServiceProperty(eth1, shill::kStateProperty,
340                                    connection_state_idle_value);
341   message_loop_.RunUntilIdle();
342   EXPECT_EQ(shill::kStateIdle,
343             test_observer_->NetworkConnectionStateForService(eth1));
344   EXPECT_EQ(2, test_observer_->ConnectionStateChangesForService(eth1));
345   // Confirm that changing the connection state to the same value does *not*
346   // signal the observer.
347   service_test->SetServiceProperty(eth1, shill::kStateProperty,
348                                    connection_state_idle_value);
349   message_loop_.RunUntilIdle();
350   EXPECT_EQ(2, test_observer_->ConnectionStateChangesForService(eth1));
351 }
352 
TEST_F(NetworkStateHandlerTest,DefaultServiceChanged)353 TEST_F(NetworkStateHandlerTest, DefaultServiceChanged) {
354   ShillManagerClient::TestInterface* manager_test =
355       DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface();
356   ASSERT_TRUE(manager_test);
357   ShillServiceClient::TestInterface* service_test =
358       DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
359   ASSERT_TRUE(service_test);
360 
361   // Change the default network by  changing the state of eth1 to Idle which
362   // should re-sort Manager.Services.
363   const std::string eth1 = kShillManagerClientStubDefaultService;
364   const std::string wifi1 = kShillManagerClientStubDefaultWireless;
365   base::StringValue connection_state_idle_value(shill::kStateIdle);
366   service_test->SetServiceProperty(eth1, shill::kStateProperty,
367                                    connection_state_idle_value);
368   message_loop_.RunUntilIdle();
369   EXPECT_EQ(wifi1, test_observer_->default_network());
370   EXPECT_EQ(shill::kStateOnline,
371             test_observer_->default_network_connection_state());
372   // We should have seen 2 default network updates - for the default
373   // service change, and for the state change.
374   EXPECT_EQ(2u, test_observer_->default_network_change_count());
375 
376   // Updating a property on the default network should trigger
377   // a default network change.
378   DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
379       dbus::ObjectPath(wifi1),
380       shill::kSecurityProperty, base::StringValue("TestSecurity"),
381       base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
382   message_loop_.RunUntilIdle();
383   EXPECT_EQ(3u, test_observer_->default_network_change_count());
384 
385   // No default network updates for signal strength changes.
386   DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
387       dbus::ObjectPath(wifi1),
388       shill::kSignalStrengthProperty, base::FundamentalValue(32),
389       base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
390   message_loop_.RunUntilIdle();
391   EXPECT_EQ(3u, test_observer_->default_network_change_count());
392 }
393 
TEST_F(NetworkStateHandlerTest,RequestUpdate)394 TEST_F(NetworkStateHandlerTest, RequestUpdate) {
395   // Request an update for kShillManagerClientStubDefaultWireless.
396   EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(
397       kShillManagerClientStubDefaultWireless));
398   network_state_handler_->RequestUpdateForNetwork(
399       kShillManagerClientStubDefaultWireless);
400   message_loop_.RunUntilIdle();
401   EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(
402       kShillManagerClientStubDefaultWireless));
403 
404   // Request an update for all networks.
405   network_state_handler_->RequestUpdateForAllNetworks();
406   message_loop_.RunUntilIdle();
407   // kShillManagerClientStubDefaultWireless should now have 3 updates
408   EXPECT_EQ(3, test_observer_->PropertyUpdatesForService(
409       kShillManagerClientStubDefaultWireless));
410   // Other networks should have 2 updates (inital + request).
411   EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(
412       kShillManagerClientStubDefaultService));
413   EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(
414       kShillManagerClientStubWireless2));
415   EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(
416       kShillManagerClientStubCellular));
417 }
418 
419 }  // namespace chromeos
420