network_state_handler_unittest.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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
27namespace {
28
29void ErrorCallbackFunction(const std::string& error_name,
30                           const std::string& error_message) {
31  LOG(ERROR) << "Shill Error: " << error_name << " : " << error_message;
32}
33
34const std::string kShillManagerClientStubDefaultService = "eth1";
35const std::string kShillManagerClientStubDefaultWireless = "wifi1";
36const std::string kShillManagerClientStubWireless2 = "wifi2";
37const std::string kShillManagerClientStubCellular = "cellular1";
38
39using chromeos::NetworkState;
40using chromeos::NetworkStateHandler;
41
42class 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    DVLOG(1) << "DefaultNetworkChanged: " << default_network_
78             << " State: " << default_network_connection_state_;
79  }
80
81  virtual void NetworkConnectionStateChanged(
82      const NetworkState* network) OVERRIDE {
83    network_connection_state_[network->path()] = network->connection_state();
84    connection_state_changes_[network->path()]++;
85  }
86
87  virtual void NetworkPropertiesUpdated(const NetworkState* network) OVERRIDE {
88    DCHECK(network);
89    property_updates_[network->path()]++;
90  }
91
92  size_t device_list_changed_count() { return device_list_changed_count_; }
93  size_t network_count() { return network_count_; }
94  size_t default_network_change_count() {
95    return default_network_change_count_;
96  }
97  void reset_network_change_count() {
98    DVLOG(1) << "ResetNetworkChangeCount";
99    default_network_change_count_ = 0;
100  }
101  std::string default_network() { return default_network_; }
102  std::string default_network_connection_state() {
103    return default_network_connection_state_;
104  }
105  size_t favorite_count() { return favorite_count_; }
106
107  int PropertyUpdatesForService(const std::string& service_path) {
108    return property_updates_[service_path];
109  }
110
111  int ConnectionStateChangesForService(const std::string& service_path) {
112    return connection_state_changes_[service_path];
113  }
114
115  std::string NetworkConnectionStateForService(
116      const std::string& service_path) {
117    return network_connection_state_[service_path];
118  }
119
120 private:
121  NetworkStateHandler* handler_;
122  size_t device_list_changed_count_;
123  size_t network_count_;
124  size_t default_network_change_count_;
125  std::string default_network_;
126  std::string default_network_connection_state_;
127  size_t favorite_count_;
128  std::map<std::string, int> property_updates_;
129  std::map<std::string, int> connection_state_changes_;
130  std::map<std::string, std::string> network_connection_state_;
131
132  DISALLOW_COPY_AND_ASSIGN(TestObserver);
133};
134
135}  // namespace
136
137namespace chromeos {
138
139class NetworkStateHandlerTest : public testing::Test {
140 public:
141  NetworkStateHandlerTest()
142      : device_test_(NULL), manager_test_(NULL), service_test_(NULL) {}
143  virtual ~NetworkStateHandlerTest() {}
144
145  virtual void SetUp() OVERRIDE {
146    // Initialize DBusThreadManager with a stub implementation.
147    DBusThreadManager::InitializeWithStub();
148    SetupNetworkStateHandler();
149    message_loop_.RunUntilIdle();
150  }
151
152  virtual void TearDown() OVERRIDE {
153    network_state_handler_->RemoveObserver(test_observer_.get(), FROM_HERE);
154    test_observer_.reset();
155    network_state_handler_.reset();
156    DBusThreadManager::Shutdown();
157  }
158
159  void SetupNetworkStateHandler() {
160    SetupDefaultShillState();
161    network_state_handler_.reset(new NetworkStateHandler);
162    test_observer_.reset(new TestObserver(network_state_handler_.get()));
163    network_state_handler_->AddObserver(test_observer_.get(), FROM_HERE);
164    network_state_handler_->InitShillPropertyHandler();
165  }
166
167 protected:
168  void SetupDefaultShillState() {
169    message_loop_.RunUntilIdle();  // Process any pending updates
170    device_test_ =
171        DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface();
172    ASSERT_TRUE(device_test_);
173    device_test_->ClearDevices();
174    device_test_->AddDevice(
175        "/device/stub_wifi_device1", shill::kTypeWifi, "stub_wifi_device1");
176    device_test_->AddDevice("/device/stub_cellular_device1",
177                            shill::kTypeCellular,
178                            "stub_cellular_device1");
179
180    manager_test_ =
181        DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface();
182    ASSERT_TRUE(manager_test_);
183
184    service_test_ =
185        DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
186    ASSERT_TRUE(service_test_);
187    service_test_->ClearServices();
188    const bool add_to_visible = true;
189    const bool add_to_watchlist = true;
190    service_test_->AddService(kShillManagerClientStubDefaultService,
191                              kShillManagerClientStubDefaultService,
192                              shill::kTypeEthernet,
193                              shill::kStateOnline,
194                              add_to_visible,
195                              add_to_watchlist);
196    service_test_->AddService(kShillManagerClientStubDefaultWireless,
197                              kShillManagerClientStubDefaultWireless,
198                              shill::kTypeWifi,
199                              shill::kStateOnline,
200                              add_to_visible,
201                              add_to_watchlist);
202    service_test_->AddService(kShillManagerClientStubWireless2,
203                              kShillManagerClientStubWireless2,
204                              shill::kTypeWifi,
205                              shill::kStateIdle,
206                              add_to_visible,
207                              add_to_watchlist);
208    service_test_->AddService(kShillManagerClientStubCellular,
209                              kShillManagerClientStubCellular,
210                              shill::kTypeCellular,
211                              shill::kStateIdle,
212                              add_to_visible,
213                              add_to_watchlist);
214  }
215
216  base::MessageLoopForUI message_loop_;
217  scoped_ptr<NetworkStateHandler> network_state_handler_;
218  scoped_ptr<TestObserver> test_observer_;
219  ShillDeviceClient::TestInterface* device_test_;
220  ShillManagerClient::TestInterface* manager_test_;
221  ShillServiceClient::TestInterface* service_test_;
222
223 private:
224  DISALLOW_COPY_AND_ASSIGN(NetworkStateHandlerTest);
225};
226
227TEST_F(NetworkStateHandlerTest, NetworkStateHandlerStub) {
228  // Ensure that the network list is the expected size.
229  const size_t kNumShillManagerClientStubImplServices = 4;
230  EXPECT_EQ(kNumShillManagerClientStubImplServices,
231            test_observer_->network_count());
232  // Ensure that the first stub network is the default network.
233  EXPECT_EQ(kShillManagerClientStubDefaultService,
234            test_observer_->default_network());
235  EXPECT_EQ(kShillManagerClientStubDefaultService,
236            network_state_handler_->ConnectedNetworkByType(
237                NetworkTypePattern::Default())->path());
238  EXPECT_EQ(kShillManagerClientStubDefaultService,
239            network_state_handler_->ConnectedNetworkByType(
240                NetworkTypePattern::Ethernet())->path());
241  EXPECT_EQ(kShillManagerClientStubDefaultWireless,
242            network_state_handler_->ConnectedNetworkByType(
243                NetworkTypePattern::Wireless())->path());
244  EXPECT_EQ(kShillManagerClientStubCellular,
245            network_state_handler_->FirstNetworkByType(
246                NetworkTypePattern::Mobile())->path());
247  EXPECT_EQ(
248      kShillManagerClientStubCellular,
249      network_state_handler_->FirstNetworkByType(NetworkTypePattern::Cellular())
250          ->path());
251  EXPECT_EQ(shill::kStateOnline,
252            test_observer_->default_network_connection_state());
253}
254
255TEST_F(NetworkStateHandlerTest, TechnologyChanged) {
256  // There may be several manager changes during initialization.
257  size_t initial_changed_count = test_observer_->device_list_changed_count();
258  // Disable a technology.
259  network_state_handler_->SetTechnologyEnabled(
260      NetworkTypePattern::Wimax(), false, network_handler::ErrorCallback());
261  EXPECT_NE(
262      NetworkStateHandler::TECHNOLOGY_ENABLED,
263      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
264  EXPECT_EQ(initial_changed_count + 1,
265            test_observer_->device_list_changed_count());
266  // Enable a technology.
267  network_state_handler_->SetTechnologyEnabled(
268      NetworkTypePattern::Wimax(), true, network_handler::ErrorCallback());
269  // The technology state should immediately change to ENABLING and we should
270  // receive a manager changed callback.
271  EXPECT_EQ(initial_changed_count + 2,
272            test_observer_->device_list_changed_count());
273  EXPECT_EQ(
274      NetworkStateHandler::TECHNOLOGY_ENABLING,
275      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
276  message_loop_.RunUntilIdle();
277  // Ensure we receive 2 manager changed callbacks when the technology becomes
278  // avalable and enabled.
279  EXPECT_EQ(initial_changed_count + 4,
280            test_observer_->device_list_changed_count());
281  EXPECT_EQ(
282      NetworkStateHandler::TECHNOLOGY_ENABLED,
283      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
284}
285
286TEST_F(NetworkStateHandlerTest, TechnologyState) {
287  manager_test_->RemoveTechnology(shill::kTypeWimax);
288  message_loop_.RunUntilIdle();
289  EXPECT_EQ(
290      NetworkStateHandler::TECHNOLOGY_UNAVAILABLE,
291      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
292
293  manager_test_->AddTechnology(shill::kTypeWimax, false);
294  message_loop_.RunUntilIdle();
295  EXPECT_EQ(
296      NetworkStateHandler::TECHNOLOGY_AVAILABLE,
297      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
298
299  manager_test_->SetTechnologyInitializing(shill::kTypeWimax, true);
300  message_loop_.RunUntilIdle();
301  EXPECT_EQ(
302      NetworkStateHandler::TECHNOLOGY_UNINITIALIZED,
303      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
304
305  manager_test_->SetTechnologyInitializing(shill::kTypeWimax, false);
306  network_state_handler_->SetTechnologyEnabled(
307      NetworkTypePattern::Wimax(), true, network_handler::ErrorCallback());
308  message_loop_.RunUntilIdle();
309  EXPECT_EQ(
310      NetworkStateHandler::TECHNOLOGY_ENABLED,
311      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
312
313  manager_test_->RemoveTechnology(shill::kTypeWimax);
314  message_loop_.RunUntilIdle();
315  EXPECT_EQ(
316      NetworkStateHandler::TECHNOLOGY_UNAVAILABLE,
317      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
318}
319
320TEST_F(NetworkStateHandlerTest, ServicePropertyChanged) {
321  // Set a service property.
322  const std::string eth1 = kShillManagerClientStubDefaultService;
323  const NetworkState* ethernet = network_state_handler_->GetNetworkState(eth1);
324  ASSERT_TRUE(ethernet);
325  EXPECT_EQ("", ethernet->security());
326  EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(eth1));
327  base::StringValue security_value("TestSecurity");
328  DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
329      dbus::ObjectPath(eth1),
330      shill::kSecurityProperty, security_value,
331      base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
332  message_loop_.RunUntilIdle();
333  ethernet = network_state_handler_->GetNetworkState(eth1);
334  EXPECT_EQ("TestSecurity", ethernet->security());
335  EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(eth1));
336
337  // Changing a service to the existing value should not trigger an update.
338  DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
339      dbus::ObjectPath(eth1),
340      shill::kSecurityProperty, security_value,
341      base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
342  message_loop_.RunUntilIdle();
343  EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(eth1));
344}
345
346TEST_F(NetworkStateHandlerTest, FavoriteState) {
347  // Set the profile entry of a service
348  const std::string wifi1 = kShillManagerClientStubDefaultWireless;
349  ShillProfileClient::TestInterface* profile_test =
350      DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface();
351  EXPECT_TRUE(profile_test->AddService("/profile/default", wifi1));
352  message_loop_.RunUntilIdle();
353  network_state_handler_->UpdateManagerProperties();
354  message_loop_.RunUntilIdle();
355  EXPECT_EQ(1u, test_observer_->favorite_count());
356}
357
358TEST_F(NetworkStateHandlerTest, NetworkConnectionStateChanged) {
359  // Change a network state.
360  const std::string eth1 = kShillManagerClientStubDefaultService;
361  base::StringValue connection_state_idle_value(shill::kStateIdle);
362  service_test_->SetServiceProperty(eth1, shill::kStateProperty,
363                                   connection_state_idle_value);
364  message_loop_.RunUntilIdle();
365  EXPECT_EQ(shill::kStateIdle,
366            test_observer_->NetworkConnectionStateForService(eth1));
367  EXPECT_EQ(2, test_observer_->ConnectionStateChangesForService(eth1));
368  // Confirm that changing the connection state to the same value does *not*
369  // signal the observer.
370  service_test_->SetServiceProperty(eth1, shill::kStateProperty,
371                                   connection_state_idle_value);
372  message_loop_.RunUntilIdle();
373  EXPECT_EQ(2, test_observer_->ConnectionStateChangesForService(eth1));
374}
375
376TEST_F(NetworkStateHandlerTest, DefaultServiceDisconnected) {
377  const std::string eth1 = kShillManagerClientStubDefaultService;
378  const std::string wifi1 = kShillManagerClientStubDefaultWireless;
379
380  // Disconnect ethernet.
381  test_observer_->reset_network_change_count();
382  base::StringValue connection_state_idle_value(shill::kStateIdle);
383  service_test_->SetServiceProperty(eth1, shill::kStateProperty,
384                                    connection_state_idle_value);
385  message_loop_.RunUntilIdle();
386  // Expect two changes: first when eth1 becomes disconnected, second when
387  // wifi1 becomes the default.
388  EXPECT_EQ(2u, test_observer_->default_network_change_count());
389  EXPECT_EQ(wifi1, test_observer_->default_network());
390
391  // Disconnect wifi.
392  test_observer_->reset_network_change_count();
393  service_test_->SetServiceProperty(wifi1, shill::kStateProperty,
394                                    connection_state_idle_value);
395  message_loop_.RunUntilIdle();
396  EXPECT_EQ(1u, test_observer_->default_network_change_count());
397  EXPECT_EQ("", test_observer_->default_network());
398}
399
400TEST_F(NetworkStateHandlerTest, DefaultServiceConnected) {
401  const std::string eth1 = kShillManagerClientStubDefaultService;
402  const std::string wifi1 = kShillManagerClientStubDefaultWireless;
403
404  // Disconnect ethernet and wifi.
405  base::StringValue connection_state_idle_value(shill::kStateIdle);
406  service_test_->SetServiceProperty(eth1, shill::kStateProperty,
407                                    connection_state_idle_value);
408  service_test_->SetServiceProperty(wifi1, shill::kStateProperty,
409                                    connection_state_idle_value);
410  message_loop_.RunUntilIdle();
411  EXPECT_EQ(std::string(), test_observer_->default_network());
412
413  // Connect ethernet, should become the default network.
414  test_observer_->reset_network_change_count();
415  base::StringValue connection_state_ready_value(shill::kStateReady);
416  service_test_->SetServiceProperty(eth1, shill::kStateProperty,
417                                    connection_state_ready_value);
418  message_loop_.RunUntilIdle();
419  EXPECT_EQ(eth1, test_observer_->default_network());
420  EXPECT_EQ(shill::kStateReady,
421            test_observer_->default_network_connection_state());
422  EXPECT_EQ(1u, test_observer_->default_network_change_count());
423}
424
425TEST_F(NetworkStateHandlerTest, DefaultServiceChanged) {
426  const std::string eth1 = kShillManagerClientStubDefaultService;
427  // The default service should be eth1.
428  EXPECT_EQ(eth1, test_observer_->default_network());
429
430  // Change the default network by changing Manager.DefaultService.
431  test_observer_->reset_network_change_count();
432  const std::string wifi1 = kShillManagerClientStubDefaultWireless;
433  base::StringValue wifi1_value(wifi1);
434  manager_test_->SetManagerProperty(
435      shill::kDefaultServiceProperty, wifi1_value);
436  message_loop_.RunUntilIdle();
437  EXPECT_EQ(wifi1, test_observer_->default_network());
438  EXPECT_EQ(1u, test_observer_->default_network_change_count());
439
440  // Change the state of the default network.
441  test_observer_->reset_network_change_count();
442  base::StringValue connection_state_ready_value(shill::kStateReady);
443  service_test_->SetServiceProperty(wifi1, shill::kStateProperty,
444                                   connection_state_ready_value);
445  message_loop_.RunUntilIdle();
446  EXPECT_EQ(shill::kStateReady,
447            test_observer_->default_network_connection_state());
448  EXPECT_EQ(1u, test_observer_->default_network_change_count());
449
450  // Updating a property on the default network should trigger
451  // a default network change.
452  test_observer_->reset_network_change_count();
453  DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
454      dbus::ObjectPath(wifi1),
455      shill::kSecurityProperty, base::StringValue("TestSecurity"),
456      base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
457  message_loop_.RunUntilIdle();
458  EXPECT_EQ(1u, test_observer_->default_network_change_count());
459
460  // No default network updates for signal strength changes.
461  test_observer_->reset_network_change_count();
462  DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
463      dbus::ObjectPath(wifi1),
464      shill::kSignalStrengthProperty, base::FundamentalValue(32),
465      base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
466  message_loop_.RunUntilIdle();
467  EXPECT_EQ(0u, test_observer_->default_network_change_count());
468}
469
470TEST_F(NetworkStateHandlerTest, RequestUpdate) {
471  // Request an update for kShillManagerClientStubDefaultWireless.
472  EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(
473      kShillManagerClientStubDefaultWireless));
474  network_state_handler_->RequestUpdateForNetwork(
475      kShillManagerClientStubDefaultWireless);
476  message_loop_.RunUntilIdle();
477  EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(
478      kShillManagerClientStubDefaultWireless));
479}
480
481}  // namespace chromeos
482