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
27 namespace {
28
ErrorCallbackFunction(const std::string & error_name,const std::string & error_message)29 void ErrorCallbackFunction(const std::string& error_name,
30 const std::string& error_message) {
31 LOG(ERROR) << "Shill Error: " << error_name << " : " << error_message;
32 }
33
34 const std::string kShillManagerClientStubDefaultService = "eth1";
35 const std::string kShillManagerClientStubDefaultWireless = "wifi1";
36 const std::string kShillManagerClientStubWireless2 = "wifi2";
37 const std::string kShillManagerClientStubCellular = "cellular1";
38
39 using chromeos::NetworkState;
40 using chromeos::NetworkStateHandler;
41
42 class TestObserver : public chromeos::NetworkStateHandlerObserver {
43 public:
TestObserver(NetworkStateHandler * handler)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
~TestObserver()52 virtual ~TestObserver() {
53 }
54
DeviceListChanged()55 virtual void DeviceListChanged() OVERRIDE {
56 ++device_list_changed_count_;
57 }
58
NetworkListChanged()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
DefaultNetworkChanged(const NetworkState * network)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
NetworkConnectionStateChanged(const NetworkState * network)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
NetworkPropertiesUpdated(const NetworkState * network)85 virtual void NetworkPropertiesUpdated(const NetworkState* network) OVERRIDE {
86 DCHECK(network);
87 property_updates_[network->path()]++;
88 }
89
device_list_changed_count()90 size_t device_list_changed_count() { return device_list_changed_count_; }
network_count()91 size_t network_count() { return network_count_; }
default_network_change_count()92 size_t default_network_change_count() {
93 return default_network_change_count_;
94 }
default_network()95 std::string default_network() { return default_network_; }
default_network_connection_state()96 std::string default_network_connection_state() {
97 return default_network_connection_state_;
98 }
favorite_count()99 size_t favorite_count() { return favorite_count_; }
100
PropertyUpdatesForService(const std::string & service_path)101 int PropertyUpdatesForService(const std::string& service_path) {
102 return property_updates_[service_path];
103 }
104
ConnectionStateChangesForService(const std::string & service_path)105 int ConnectionStateChangesForService(const std::string& service_path) {
106 return connection_state_changes_[service_path];
107 }
108
NetworkConnectionStateForService(const std::string & service_path)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 device_list_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
131 namespace chromeos {
132
133 class NetworkStateHandlerTest : public testing::Test {
134 public:
NetworkStateHandlerTest()135 NetworkStateHandlerTest() {}
~NetworkStateHandlerTest()136 virtual ~NetworkStateHandlerTest() {}
137
SetUp()138 virtual void SetUp() OVERRIDE {
139 // Initialize DBusThreadManager with a stub implementation.
140 DBusThreadManager::InitializeWithStub();
141 SetupNetworkStateHandler();
142 message_loop_.RunUntilIdle();
143 }
144
TearDown()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
SetupNetworkStateHandler()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:
SetupDefaultShillState()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 shill::kTypeWifi, "stub_wifi_device1");
168 device_test->AddDevice("/device/stub_cellular_device1",
169 shill::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 shill::kTypeEthernet, shill::kStateOnline,
179 add_to_visible, add_to_watchlist);
180 service_test->AddService(kShillManagerClientStubDefaultWireless,
181 kShillManagerClientStubDefaultWireless,
182 shill::kTypeWifi, shill::kStateOnline,
183 add_to_visible, add_to_watchlist);
184 service_test->AddService(kShillManagerClientStubWireless2,
185 kShillManagerClientStubWireless2,
186 shill::kTypeWifi, shill::kStateIdle,
187 add_to_visible, add_to_watchlist);
188 service_test->AddService(kShillManagerClientStubCellular,
189 kShillManagerClientStubCellular,
190 shill::kTypeCellular, shill::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
TEST_F(NetworkStateHandlerTest,NetworkStateHandlerStub)202 TEST_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(shill::kStateOnline,
227 test_observer_->default_network_connection_state());
228 }
229
TEST_F(NetworkStateHandlerTest,TechnologyChanged)230 TEST_F(NetworkStateHandlerTest, TechnologyChanged) {
231 // There may be several manager changes during initialization.
232 size_t initial_changed_count = test_observer_->device_list_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,
240 test_observer_->device_list_changed_count());
241 // Enable a technology.
242 network_state_handler_->SetTechnologyEnabled(
243 NetworkTypePattern::Wimax(), true, network_handler::ErrorCallback());
244 // The technology state should immediately change to ENABLING and we should
245 // receive a manager changed callback.
246 EXPECT_EQ(initial_changed_count + 2,
247 test_observer_->device_list_changed_count());
248 EXPECT_EQ(
249 NetworkStateHandler::TECHNOLOGY_ENABLING,
250 network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
251 message_loop_.RunUntilIdle();
252 // Ensure we receive 2 manager changed callbacks when the technology becomes
253 // avalable and enabled.
254 EXPECT_EQ(initial_changed_count + 4,
255 test_observer_->device_list_changed_count());
256 EXPECT_EQ(
257 NetworkStateHandler::TECHNOLOGY_ENABLED,
258 network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
259 }
260
TEST_F(NetworkStateHandlerTest,TechnologyState)261 TEST_F(NetworkStateHandlerTest, TechnologyState) {
262 ShillManagerClient::TestInterface* manager_test =
263 DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface();
264 manager_test->RemoveTechnology(shill::kTypeWimax);
265 message_loop_.RunUntilIdle();
266 EXPECT_EQ(
267 NetworkStateHandler::TECHNOLOGY_UNAVAILABLE,
268 network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
269
270 manager_test->AddTechnology(shill::kTypeWimax, false);
271 message_loop_.RunUntilIdle();
272 EXPECT_EQ(
273 NetworkStateHandler::TECHNOLOGY_AVAILABLE,
274 network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
275
276 manager_test->SetTechnologyInitializing(shill::kTypeWimax, true);
277 message_loop_.RunUntilIdle();
278 EXPECT_EQ(
279 NetworkStateHandler::TECHNOLOGY_UNINITIALIZED,
280 network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
281
282 manager_test->SetTechnologyInitializing(shill::kTypeWimax, false);
283 network_state_handler_->SetTechnologyEnabled(
284 NetworkTypePattern::Wimax(), true, network_handler::ErrorCallback());
285 message_loop_.RunUntilIdle();
286 EXPECT_EQ(
287 NetworkStateHandler::TECHNOLOGY_ENABLED,
288 network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
289
290 manager_test->RemoveTechnology(shill::kTypeWimax);
291 message_loop_.RunUntilIdle();
292 EXPECT_EQ(
293 NetworkStateHandler::TECHNOLOGY_UNAVAILABLE,
294 network_state_handler_->GetTechnologyState(NetworkTypePattern::Wimax()));
295 }
296
TEST_F(NetworkStateHandlerTest,ServicePropertyChanged)297 TEST_F(NetworkStateHandlerTest, ServicePropertyChanged) {
298 // Set a service property.
299 const std::string eth1 = kShillManagerClientStubDefaultService;
300 EXPECT_EQ("", network_state_handler_->GetNetworkState(eth1)->security());
301 EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(eth1));
302 base::StringValue security_value("TestSecurity");
303 DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
304 dbus::ObjectPath(eth1),
305 shill::kSecurityProperty, security_value,
306 base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
307 message_loop_.RunUntilIdle();
308 EXPECT_EQ("TestSecurity",
309 network_state_handler_->GetNetworkState(eth1)->security());
310 EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(eth1));
311
312 // Changing a service to the existing value should not trigger an update.
313 DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
314 dbus::ObjectPath(eth1),
315 shill::kSecurityProperty, security_value,
316 base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
317 message_loop_.RunUntilIdle();
318 EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(eth1));
319 }
320
TEST_F(NetworkStateHandlerTest,FavoriteState)321 TEST_F(NetworkStateHandlerTest, FavoriteState) {
322 // Set the profile entry of a service
323 const std::string wifi1 = kShillManagerClientStubDefaultWireless;
324 ShillProfileClient::TestInterface* profile_test =
325 DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface();
326 EXPECT_TRUE(profile_test->AddService("/profile/default", wifi1));
327 message_loop_.RunUntilIdle();
328 network_state_handler_->UpdateManagerProperties();
329 message_loop_.RunUntilIdle();
330 EXPECT_EQ(1u, test_observer_->favorite_count());
331 }
332
TEST_F(NetworkStateHandlerTest,NetworkConnectionStateChanged)333 TEST_F(NetworkStateHandlerTest, NetworkConnectionStateChanged) {
334 // Change a network state.
335 ShillServiceClient::TestInterface* service_test =
336 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
337 const std::string eth1 = kShillManagerClientStubDefaultService;
338 base::StringValue connection_state_idle_value(shill::kStateIdle);
339 service_test->SetServiceProperty(eth1, shill::kStateProperty,
340 connection_state_idle_value);
341 message_loop_.RunUntilIdle();
342 EXPECT_EQ(shill::kStateIdle,
343 test_observer_->NetworkConnectionStateForService(eth1));
344 EXPECT_EQ(2, test_observer_->ConnectionStateChangesForService(eth1));
345 // Confirm that changing the connection state to the same value does *not*
346 // signal the observer.
347 service_test->SetServiceProperty(eth1, shill::kStateProperty,
348 connection_state_idle_value);
349 message_loop_.RunUntilIdle();
350 EXPECT_EQ(2, test_observer_->ConnectionStateChangesForService(eth1));
351 }
352
TEST_F(NetworkStateHandlerTest,DefaultServiceChanged)353 TEST_F(NetworkStateHandlerTest, DefaultServiceChanged) {
354 ShillManagerClient::TestInterface* manager_test =
355 DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface();
356 ASSERT_TRUE(manager_test);
357 ShillServiceClient::TestInterface* service_test =
358 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
359 ASSERT_TRUE(service_test);
360
361 // Change the default network by changing the state of eth1 to Idle which
362 // should re-sort Manager.Services.
363 const std::string eth1 = kShillManagerClientStubDefaultService;
364 const std::string wifi1 = kShillManagerClientStubDefaultWireless;
365 base::StringValue connection_state_idle_value(shill::kStateIdle);
366 service_test->SetServiceProperty(eth1, shill::kStateProperty,
367 connection_state_idle_value);
368 message_loop_.RunUntilIdle();
369 EXPECT_EQ(wifi1, test_observer_->default_network());
370 EXPECT_EQ(shill::kStateOnline,
371 test_observer_->default_network_connection_state());
372 // We should have seen 2 default network updates - for the default
373 // service change, and for the state change.
374 EXPECT_EQ(2u, test_observer_->default_network_change_count());
375
376 // Updating a property on the default network should trigger
377 // a default network change.
378 DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
379 dbus::ObjectPath(wifi1),
380 shill::kSecurityProperty, base::StringValue("TestSecurity"),
381 base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
382 message_loop_.RunUntilIdle();
383 EXPECT_EQ(3u, test_observer_->default_network_change_count());
384
385 // No default network updates for signal strength changes.
386 DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
387 dbus::ObjectPath(wifi1),
388 shill::kSignalStrengthProperty, base::FundamentalValue(32),
389 base::Bind(&base::DoNothing), base::Bind(&ErrorCallbackFunction));
390 message_loop_.RunUntilIdle();
391 EXPECT_EQ(3u, test_observer_->default_network_change_count());
392 }
393
TEST_F(NetworkStateHandlerTest,RequestUpdate)394 TEST_F(NetworkStateHandlerTest, RequestUpdate) {
395 // Request an update for kShillManagerClientStubDefaultWireless.
396 EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(
397 kShillManagerClientStubDefaultWireless));
398 network_state_handler_->RequestUpdateForNetwork(
399 kShillManagerClientStubDefaultWireless);
400 message_loop_.RunUntilIdle();
401 EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(
402 kShillManagerClientStubDefaultWireless));
403
404 // Request an update for all networks.
405 network_state_handler_->RequestUpdateForAllNetworks();
406 message_loop_.RunUntilIdle();
407 // kShillManagerClientStubDefaultWireless should now have 3 updates
408 EXPECT_EQ(3, test_observer_->PropertyUpdatesForService(
409 kShillManagerClientStubDefaultWireless));
410 // Other networks should have 2 updates (inital + request).
411 EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(
412 kShillManagerClientStubDefaultService));
413 EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(
414 kShillManagerClientStubWireless2));
415 EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(
416 kShillManagerClientStubCellular));
417 }
418
419 } // namespace chromeos
420