network_state_handler_unittest.cc revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
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 = "stub_ethernet";
33const std::string kShillManagerClientStubDefaultWireless = "stub_wifi1";
34const std::string kShillManagerClientStubWireless2 = "stub_wifi2";
35const std::string kShillManagerClientStubCellular = "stub_cellular";
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_.reset();
139    test_observer_.reset();
140    DBusThreadManager::Shutdown();
141  }
142
143  void SetupNetworkStateHandler() {
144    SetupDefaultShillState();
145    network_state_handler_.reset(new NetworkStateHandler);
146    test_observer_.reset(new TestObserver(network_state_handler_.get()));
147    network_state_handler_->AddObserver(test_observer_.get());
148    network_state_handler_->InitShillPropertyHandler();
149  }
150
151 protected:
152  void SetupDefaultShillState() {
153    message_loop_.RunUntilIdle();  // Process any pending updates
154    ShillDeviceClient::TestInterface* device_test =
155        DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface();
156    device_test->ClearDevices();
157    device_test->AddDevice("/device/stub_wifi_device1",
158                           flimflam::kTypeWifi, "stub_wifi_device1");
159    device_test->AddDevice("/device/stub_cellular_device1",
160                           flimflam::kTypeCellular, "stub_cellular_device1");
161
162    ShillServiceClient::TestInterface* service_test =
163        DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
164    service_test->ClearServices();
165    const bool add_to_watchlist = true;
166    service_test->AddService(kShillManagerClientStubDefaultService,
167                             kShillManagerClientStubDefaultService,
168                             flimflam::kTypeEthernet, flimflam::kStateOnline,
169                             add_to_watchlist);
170    service_test->AddService(kShillManagerClientStubDefaultWireless,
171                             kShillManagerClientStubDefaultWireless,
172                             flimflam::kTypeWifi, flimflam::kStateOnline,
173                             add_to_watchlist);
174    service_test->AddService(kShillManagerClientStubWireless2,
175                             kShillManagerClientStubWireless2,
176                             flimflam::kTypeWifi, flimflam::kStateIdle,
177                             add_to_watchlist);
178    service_test->AddService(kShillManagerClientStubCellular,
179                             kShillManagerClientStubCellular,
180                             flimflam::kTypeCellular, flimflam::kStateIdle,
181                             add_to_watchlist);
182  }
183
184  MessageLoopForUI message_loop_;
185  scoped_ptr<NetworkStateHandler> network_state_handler_;
186  scoped_ptr<TestObserver> test_observer_;
187
188 private:
189  DISALLOW_COPY_AND_ASSIGN(NetworkStateHandlerTest);
190};
191
192TEST_F(NetworkStateHandlerTest, NetworkStateHandlerStub) {
193  EXPECT_EQ(1u, test_observer_->manager_changed_count());
194  // Ensure that the network list is the expected size.
195  const size_t kNumShillManagerClientStubImplServices = 4;
196  EXPECT_EQ(kNumShillManagerClientStubImplServices,
197            test_observer_->network_count());
198  // Ensure that the first stub network is the default network.
199  EXPECT_EQ(kShillManagerClientStubDefaultService,
200            test_observer_->default_network());
201  EXPECT_EQ(kShillManagerClientStubDefaultService,
202            network_state_handler_->ConnectedNetworkByType(
203                NetworkStateHandler::kMatchTypeDefault)->path());
204  EXPECT_EQ(kShillManagerClientStubDefaultService,
205            network_state_handler_->ConnectedNetworkByType(
206                flimflam::kTypeEthernet)->path());
207  EXPECT_EQ(kShillManagerClientStubDefaultWireless,
208            network_state_handler_->ConnectedNetworkByType(
209                NetworkStateHandler::kMatchTypeWireless)->path());
210  EXPECT_EQ(flimflam::kStateOnline,
211            test_observer_->default_network_connection_state());
212}
213
214TEST_F(NetworkStateHandlerTest, TechnologyChanged) {
215  EXPECT_EQ(1u, test_observer_->manager_changed_count());
216  // Enable a technology.
217  EXPECT_NE(NetworkStateHandler::TECHNOLOGY_ENABLED,
218            network_state_handler_->GetTechnologyState(flimflam::kTypeWimax));
219  network_state_handler_->SetTechnologyEnabled(
220      flimflam::kTypeWimax, true, network_handler::ErrorCallback());
221  // The technology state should immediately change to ENABLING and we should
222  // receive a manager changed callback.
223  EXPECT_EQ(2u, test_observer_->manager_changed_count());
224  EXPECT_EQ(NetworkStateHandler::TECHNOLOGY_ENABLING,
225            network_state_handler_->GetTechnologyState(flimflam::kTypeWimax));
226  message_loop_.RunUntilIdle();
227  // Ensure we receive another manager changed callbacks when the technology
228  // becomes enabled.
229  EXPECT_EQ(3u, test_observer_->manager_changed_count());
230  EXPECT_EQ(NetworkStateHandler::TECHNOLOGY_ENABLED,
231            network_state_handler_->GetTechnologyState(flimflam::kTypeWimax));
232}
233
234TEST_F(NetworkStateHandlerTest, TechnologyState) {
235  ShillManagerClient::TestInterface* manager_test =
236      DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface();
237  EXPECT_EQ(NetworkStateHandler::TECHNOLOGY_UNAVAILABLE,
238            network_state_handler_->GetTechnologyState(flimflam::kTypeWimax));
239
240  manager_test->AddTechnology(flimflam::kTypeWimax, false);
241  message_loop_.RunUntilIdle();
242  EXPECT_EQ(NetworkStateHandler::TECHNOLOGY_AVAILABLE,
243            network_state_handler_->GetTechnologyState(flimflam::kTypeWimax));
244
245  manager_test->SetTechnologyInitializing(flimflam::kTypeWimax, true);
246  message_loop_.RunUntilIdle();
247  EXPECT_EQ(NetworkStateHandler::TECHNOLOGY_UNINITIALIZED,
248            network_state_handler_->GetTechnologyState(flimflam::kTypeWimax));
249
250  manager_test->SetTechnologyInitializing(flimflam::kTypeWimax, false);
251  network_state_handler_->SetTechnologyEnabled(
252      flimflam::kTypeWimax, true, network_handler::ErrorCallback());
253  message_loop_.RunUntilIdle();
254  EXPECT_EQ(NetworkStateHandler::TECHNOLOGY_ENABLED,
255            network_state_handler_->GetTechnologyState(flimflam::kTypeWimax));
256
257  manager_test->RemoveTechnology(flimflam::kTypeWimax);
258  message_loop_.RunUntilIdle();
259  EXPECT_EQ(NetworkStateHandler::TECHNOLOGY_UNAVAILABLE,
260            network_state_handler_->GetTechnologyState(flimflam::kTypeWimax));
261}
262
263TEST_F(NetworkStateHandlerTest, ServicePropertyChanged) {
264  // Set a service property.
265  const std::string eth0 = kShillManagerClientStubDefaultService;
266  EXPECT_EQ("", network_state_handler_->GetNetworkState(eth0)->security());
267  EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(eth0));
268  base::StringValue security_value("TestSecurity");
269  DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
270      dbus::ObjectPath(eth0),
271      flimflam::kSecurityProperty, security_value,
272      base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
273  message_loop_.RunUntilIdle();
274  EXPECT_EQ("TestSecurity",
275            network_state_handler_->GetNetworkState(eth0)->security());
276  EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(eth0));
277}
278
279TEST_F(NetworkStateHandlerTest, NetworkConnectionStateChanged) {
280  // Change a network state.
281  ShillServiceClient::TestInterface* service_test =
282      DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
283  const std::string eth0 = kShillManagerClientStubDefaultService;
284  base::StringValue connection_state_idle_value(flimflam::kStateIdle);
285  service_test->SetServiceProperty(eth0, flimflam::kStateProperty,
286                                   connection_state_idle_value);
287  message_loop_.RunUntilIdle();
288  EXPECT_EQ(flimflam::kStateIdle,
289            test_observer_->NetworkConnectionStateForService(eth0));
290  EXPECT_EQ(2, test_observer_->ConnectionStateChangesForService(eth0));
291  // Confirm that changing the connection state to the same value does *not*
292  // signal the observer.
293  service_test->SetServiceProperty(eth0, flimflam::kStateProperty,
294                                   connection_state_idle_value);
295  message_loop_.RunUntilIdle();
296  EXPECT_EQ(2, test_observer_->ConnectionStateChangesForService(eth0));
297}
298
299TEST_F(NetworkStateHandlerTest, DefaultServiceChanged) {
300  ShillManagerClient::TestInterface* manager_test =
301      DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface();
302  ASSERT_TRUE(manager_test);
303  ShillServiceClient::TestInterface* service_test =
304      DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
305  ASSERT_TRUE(service_test);
306
307  // Change the default network by moving wifi1 to the front of the list
308  // and changing the state of stub_ethernet to Idle.
309  const std::string wifi1 = kShillManagerClientStubDefaultWireless;
310  manager_test->MoveServiceToIndex(wifi1, 0, true);
311  const std::string eth0 = kShillManagerClientStubDefaultService;
312  base::StringValue connection_state_idle_value(flimflam::kStateIdle);
313  service_test->SetServiceProperty(eth0, flimflam::kStateProperty,
314                                   connection_state_idle_value);
315  message_loop_.RunUntilIdle();
316  EXPECT_EQ(wifi1, test_observer_->default_network());
317  EXPECT_EQ(flimflam::kStateOnline,
318            test_observer_->default_network_connection_state());
319  // We should have seen 2 default network updates - for the default
320  // service change, and for the state change.
321  EXPECT_EQ(2u, test_observer_->default_network_change_count());
322
323  // Updating a property on the default network should trigger
324  // a default network change.
325  DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
326      dbus::ObjectPath(wifi1),
327      flimflam::kSecurityProperty, base::StringValue("TestSecurity"),
328      base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
329  message_loop_.RunUntilIdle();
330  EXPECT_EQ(3u, test_observer_->default_network_change_count());
331
332  // No default network updates for signal strength changes.
333  DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
334      dbus::ObjectPath(wifi1),
335      flimflam::kSignalStrengthProperty, base::FundamentalValue(32),
336      base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
337  message_loop_.RunUntilIdle();
338  EXPECT_EQ(3u, test_observer_->default_network_change_count());
339}
340
341}  // namespace chromeos
342