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