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