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 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: 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 52 virtual ~TestObserver() { 53 } 54 55 virtual void DeviceListChanged() OVERRIDE { 56 ++device_list_changed_count_; 57 } 58 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 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 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 85 virtual void NetworkPropertiesUpdated(const NetworkState* network) OVERRIDE { 86 DCHECK(network); 87 property_updates_[network->path()]++; 88 } 89 90 size_t device_list_changed_count() { return device_list_changed_count_; } 91 size_t network_count() { return network_count_; } 92 size_t default_network_change_count() { 93 return default_network_change_count_; 94 } 95 std::string default_network() { return default_network_; } 96 std::string default_network_connection_state() { 97 return default_network_connection_state_; 98 } 99 size_t favorite_count() { return favorite_count_; } 100 101 int PropertyUpdatesForService(const std::string& service_path) { 102 return property_updates_[service_path]; 103 } 104 105 int ConnectionStateChangesForService(const std::string& service_path) { 106 return connection_state_changes_[service_path]; 107 } 108 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: 135 NetworkStateHandlerTest() {} 136 virtual ~NetworkStateHandlerTest() {} 137 138 virtual void SetUp() OVERRIDE { 139 // Initialize DBusThreadManager with a stub implementation. 140 DBusThreadManager::InitializeWithStub(); 141 SetupNetworkStateHandler(); 142 message_loop_.RunUntilIdle(); 143 } 144 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 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: 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 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 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 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 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 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 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 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 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