network_state_handler_unittest.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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        manager_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 NetworkManagerChanged() OVERRIDE {
56    ++manager_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 manager_changed_count() { return manager_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 manager_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
131namespace chromeos {
132
133class 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                           flimflam::kTypeWifi, "stub_wifi_device1");
168    device_test->AddDevice("/device/stub_cellular_device1",
169                           flimflam::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                             flimflam::kTypeEthernet, flimflam::kStateOnline,
179                             add_to_visible, add_to_watchlist);
180    service_test->AddService(kShillManagerClientStubDefaultWireless,
181                             kShillManagerClientStubDefaultWireless,
182                             flimflam::kTypeWifi, flimflam::kStateOnline,
183                             add_to_visible, add_to_watchlist);
184    service_test->AddService(kShillManagerClientStubWireless2,
185                             kShillManagerClientStubWireless2,
186                             flimflam::kTypeWifi, flimflam::kStateIdle,
187                             add_to_visible, add_to_watchlist);
188    service_test->AddService(kShillManagerClientStubCellular,
189                             kShillManagerClientStubCellular,
190                             flimflam::kTypeCellular, flimflam::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
202TEST_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(flimflam::kStateOnline,
227            test_observer_->default_network_connection_state());
228}
229
230TEST_F(NetworkStateHandlerTest, TechnologyChanged) {
231  // There may be several manager changes during initialization.
232  size_t initial_changed_count = test_observer_->manager_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, test_observer_->manager_changed_count());
240  // Enable a technology.
241  network_state_handler_->SetTechnologyEnabled(
242      NetworkTypePattern::Wimax(), true, network_handler::ErrorCallback());
243  // The technology state should immediately change to ENABLING and we should
244  // receive a manager changed callback.
245  EXPECT_EQ(initial_changed_count + 2, test_observer_->manager_changed_count());
246  EXPECT_EQ(
247      NetworkStateHandler::TECHNOLOGY_ENABLING,
248      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
249  message_loop_.RunUntilIdle();
250  // Ensure we receive 2 manager changed callbacks when the technology becomes
251  // avalable and enabled.
252  EXPECT_EQ(initial_changed_count + 4, test_observer_->manager_changed_count());
253  EXPECT_EQ(
254      NetworkStateHandler::TECHNOLOGY_ENABLED,
255      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
256}
257
258TEST_F(NetworkStateHandlerTest, TechnologyState) {
259  ShillManagerClient::TestInterface* manager_test =
260      DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface();
261  manager_test->RemoveTechnology(flimflam::kTypeWimax);
262  message_loop_.RunUntilIdle();
263  EXPECT_EQ(
264      NetworkStateHandler::TECHNOLOGY_UNAVAILABLE,
265      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
266
267  manager_test->AddTechnology(flimflam::kTypeWimax, false);
268  message_loop_.RunUntilIdle();
269  EXPECT_EQ(
270      NetworkStateHandler::TECHNOLOGY_AVAILABLE,
271      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
272
273  manager_test->SetTechnologyInitializing(flimflam::kTypeWimax, true);
274  message_loop_.RunUntilIdle();
275  EXPECT_EQ(
276      NetworkStateHandler::TECHNOLOGY_UNINITIALIZED,
277      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
278
279  manager_test->SetTechnologyInitializing(flimflam::kTypeWimax, false);
280  network_state_handler_->SetTechnologyEnabled(
281      NetworkTypePattern::Wimax(), true, network_handler::ErrorCallback());
282  message_loop_.RunUntilIdle();
283  EXPECT_EQ(
284      NetworkStateHandler::TECHNOLOGY_ENABLED,
285      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
286
287  manager_test->RemoveTechnology(flimflam::kTypeWimax);
288  message_loop_.RunUntilIdle();
289  EXPECT_EQ(
290      NetworkStateHandler::TECHNOLOGY_UNAVAILABLE,
291      network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
292}
293
294TEST_F(NetworkStateHandlerTest, ServicePropertyChanged) {
295  // Set a service property.
296  const std::string eth1 = kShillManagerClientStubDefaultService;
297  EXPECT_EQ("", network_state_handler_->GetNetworkState(eth1)->security());
298  EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(eth1));
299  base::StringValue security_value("TestSecurity");
300  DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
301      dbus::ObjectPath(eth1),
302      flimflam::kSecurityProperty, security_value,
303      base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
304  message_loop_.RunUntilIdle();
305  EXPECT_EQ("TestSecurity",
306            network_state_handler_->GetNetworkState(eth1)->security());
307  EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(eth1));
308
309  // Changing a service to the existing value should not trigger an update.
310  DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
311      dbus::ObjectPath(eth1),
312      flimflam::kSecurityProperty, security_value,
313      base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
314  message_loop_.RunUntilIdle();
315  EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(eth1));
316}
317
318TEST_F(NetworkStateHandlerTest, FavoriteState) {
319  // Set the profile entry of a service
320  const std::string wifi1 = kShillManagerClientStubDefaultWireless;
321  ShillProfileClient::TestInterface* profile_test =
322      DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface();
323  EXPECT_TRUE(profile_test->AddService("/profile/default", wifi1));
324  message_loop_.RunUntilIdle();
325  network_state_handler_->UpdateManagerProperties();
326  message_loop_.RunUntilIdle();
327  EXPECT_EQ(1u, test_observer_->favorite_count());
328}
329
330TEST_F(NetworkStateHandlerTest, NetworkConnectionStateChanged) {
331  // Change a network state.
332  ShillServiceClient::TestInterface* service_test =
333      DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
334  const std::string eth1 = kShillManagerClientStubDefaultService;
335  base::StringValue connection_state_idle_value(flimflam::kStateIdle);
336  service_test->SetServiceProperty(eth1, flimflam::kStateProperty,
337                                   connection_state_idle_value);
338  message_loop_.RunUntilIdle();
339  EXPECT_EQ(flimflam::kStateIdle,
340            test_observer_->NetworkConnectionStateForService(eth1));
341  EXPECT_EQ(2, test_observer_->ConnectionStateChangesForService(eth1));
342  // Confirm that changing the connection state to the same value does *not*
343  // signal the observer.
344  service_test->SetServiceProperty(eth1, flimflam::kStateProperty,
345                                   connection_state_idle_value);
346  message_loop_.RunUntilIdle();
347  EXPECT_EQ(2, test_observer_->ConnectionStateChangesForService(eth1));
348}
349
350TEST_F(NetworkStateHandlerTest, DefaultServiceChanged) {
351  ShillManagerClient::TestInterface* manager_test =
352      DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface();
353  ASSERT_TRUE(manager_test);
354  ShillServiceClient::TestInterface* service_test =
355      DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
356  ASSERT_TRUE(service_test);
357
358  // Change the default network by  changing the state of eth1 to Idle which
359  // should re-sort Manager.Services.
360  const std::string eth1 = kShillManagerClientStubDefaultService;
361  const std::string wifi1 = kShillManagerClientStubDefaultWireless;
362  base::StringValue connection_state_idle_value(flimflam::kStateIdle);
363  service_test->SetServiceProperty(eth1, flimflam::kStateProperty,
364                                   connection_state_idle_value);
365  message_loop_.RunUntilIdle();
366  EXPECT_EQ(wifi1, test_observer_->default_network());
367  EXPECT_EQ(flimflam::kStateOnline,
368            test_observer_->default_network_connection_state());
369  // We should have seen 2 default network updates - for the default
370  // service change, and for the state change.
371  EXPECT_EQ(2u, test_observer_->default_network_change_count());
372
373  // Updating a property on the default network should trigger
374  // a default network change.
375  DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
376      dbus::ObjectPath(wifi1),
377      flimflam::kSecurityProperty, base::StringValue("TestSecurity"),
378      base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
379  message_loop_.RunUntilIdle();
380  EXPECT_EQ(3u, test_observer_->default_network_change_count());
381
382  // No default network updates for signal strength changes.
383  DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
384      dbus::ObjectPath(wifi1),
385      flimflam::kSignalStrengthProperty, base::FundamentalValue(32),
386      base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
387  message_loop_.RunUntilIdle();
388  EXPECT_EQ(3u, test_observer_->default_network_change_count());
389}
390
391TEST_F(NetworkStateHandlerTest, RequestUpdate) {
392  // Request an update for kShillManagerClientStubDefaultWireless.
393  EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(
394      kShillManagerClientStubDefaultWireless));
395  network_state_handler_->RequestUpdateForNetwork(
396      kShillManagerClientStubDefaultWireless);
397  message_loop_.RunUntilIdle();
398  EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(
399      kShillManagerClientStubDefaultWireless));
400
401  // Request an update for all networks.
402  network_state_handler_->RequestUpdateForAllNetworks();
403  message_loop_.RunUntilIdle();
404  // kShillManagerClientStubDefaultWireless should now have 3 updates
405  EXPECT_EQ(3, test_observer_->PropertyUpdatesForService(
406      kShillManagerClientStubDefaultWireless));
407  // Other networks should have 2 updates (inital + request).
408  EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(
409      kShillManagerClientStubDefaultService));
410  EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(
411      kShillManagerClientStubWireless2));
412  EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(
413      kShillManagerClientStubCellular));
414}
415
416}  // namespace chromeos
417