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