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.
6 #include "base/json/json_writer.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/strings/string_piece.h"
9 #include "base/values.h"
10 #include "chromeos/dbus/dbus_thread_manager.h"
11 #include "chromeos/dbus/fake_dbus_thread_manager.h"
12 #include "chromeos/dbus/mock_shill_manager_client.h"
13 #include "chromeos/dbus/mock_shill_profile_client.h"
14 #include "chromeos/dbus/mock_shill_service_client.h"
15 #include "chromeos/dbus/shill_stub_helper.h"
16 #include "chromeos/network/network_configuration_handler.h"
17 #include "chromeos/network/network_state.h"
18 #include "chromeos/network/network_state_handler.h"
19 #include "chromeos/network/network_state_handler_observer.h"
20 #include "chromeos/network/shill_property_util.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "third_party/cros_system_api/dbus/service_constants.h"
26 using ::testing::AnyNumber
;
27 using ::testing::Invoke
;
28 using ::testing::Pointee
;
29 using ::testing::Return
;
30 using ::testing::SaveArg
;
31 using ::testing::StrEq
;
33 // Matcher to match base::Value.
34 MATCHER_P(IsEqualTo
, value
, "") { return arg
.Equals(value
); }
40 static std::string
PrettyJson(const base::DictionaryValue
& value
) {
42 base::JSONWriter::WriteWithOptions(&value
,
43 base::JSONWriter::OPTIONS_PRETTY_PRINT
,
48 void DictionaryValueCallback(
49 const std::string
& expected_id
,
50 const std::string
& expected_json
,
51 const std::string
& service_path
,
52 const base::DictionaryValue
& dictionary
) {
53 std::string dict_str
= PrettyJson(dictionary
);
54 EXPECT_EQ(expected_json
, dict_str
);
55 EXPECT_EQ(expected_id
, service_path
);
58 void ErrorCallback(bool error_expected
,
59 const std::string
& expected_id
,
60 const std::string
& error_name
,
61 scoped_ptr
<base::DictionaryValue
> error_data
) {
62 EXPECT_TRUE(error_expected
) << "Unexpected error: " << error_name
63 << " with associated data: \n"
64 << PrettyJson(*error_data
);
67 void StringResultCallback(const std::string
& expected_result
,
68 const std::string
& result
) {
69 EXPECT_EQ(expected_result
, result
);
72 void DBusErrorCallback(const std::string
& error_name
,
73 const std::string
& error_message
) {
74 EXPECT_TRUE(false) << "DBus Error: " << error_name
<< "("
75 << error_message
<< ")";
80 TestCallback() : run_count_(0) {}
84 int run_count() const { return run_count_
; }
92 class NetworkConfigurationHandlerTest
: public testing::Test
{
94 NetworkConfigurationHandlerTest()
95 : mock_manager_client_(NULL
),
96 mock_profile_client_(NULL
),
97 mock_service_client_(NULL
),
98 dictionary_value_result_(NULL
) {}
99 virtual ~NetworkConfigurationHandlerTest() {}
101 virtual void SetUp() OVERRIDE
{
102 FakeDBusThreadManager
* dbus_thread_manager
= new FakeDBusThreadManager
;
103 mock_manager_client_
= new MockShillManagerClient();
104 mock_profile_client_
= new MockShillProfileClient();
105 mock_service_client_
= new MockShillServiceClient();
106 dbus_thread_manager
->SetShillManagerClient(
107 scoped_ptr
<ShillManagerClient
>(mock_manager_client_
).Pass());
108 dbus_thread_manager
->SetShillProfileClient(
109 scoped_ptr
<ShillProfileClient
>(mock_profile_client_
).Pass());
110 dbus_thread_manager
->SetShillServiceClient(
111 scoped_ptr
<ShillServiceClient
>(mock_service_client_
).Pass());
113 EXPECT_CALL(*mock_service_client_
, GetProperties(_
, _
))
115 EXPECT_CALL(*mock_manager_client_
, GetProperties(_
))
117 EXPECT_CALL(*mock_manager_client_
, AddPropertyChangedObserver(_
))
119 EXPECT_CALL(*mock_manager_client_
, RemovePropertyChangedObserver(_
))
122 DBusThreadManager::InitializeForTesting(dbus_thread_manager
);
124 network_state_handler_
.reset(NetworkStateHandler::InitializeForTest());
125 network_configuration_handler_
.reset(new NetworkConfigurationHandler());
126 network_configuration_handler_
->Init(network_state_handler_
.get());
127 message_loop_
.RunUntilIdle();
130 virtual void TearDown() OVERRIDE
{
131 network_configuration_handler_
.reset();
132 network_state_handler_
.reset();
133 DBusThreadManager::Shutdown();
136 // Handles responses for GetProperties method calls.
137 void OnGetProperties(
138 const dbus::ObjectPath
& path
,
139 const ShillClientHelper::DictionaryValueCallback
& callback
) {
140 callback
.Run(DBUS_METHOD_CALL_SUCCESS
, *dictionary_value_result_
);
143 // Handles responses for SetProperties method calls.
144 void OnSetProperties(const dbus::ObjectPath
& service_path
,
145 const base::DictionaryValue
& properties
,
146 const base::Closure
& callback
,
147 const ShillClientHelper::ErrorCallback
& error_callback
) {
151 // Handles responses for ClearProperties method calls.
152 void OnClearProperties(
153 const dbus::ObjectPath
& service_path
,
154 const std::vector
<std::string
>& names
,
155 const ShillClientHelper::ListValueCallback
& callback
,
156 const ShillClientHelper::ErrorCallback
& error_callback
) {
157 base::ListValue result
;
158 result
.AppendBoolean(true);
159 callback
.Run(result
);
162 // Handles responses for ClearProperties method calls, and simulates an error
164 void OnClearPropertiesError(
165 const dbus::ObjectPath
& service_path
,
166 const std::vector
<std::string
>& names
,
167 const ShillClientHelper::ListValueCallback
& callback
,
168 const ShillClientHelper::ErrorCallback
& error_callback
) {
169 base::ListValue result
;
170 result
.AppendBoolean(false);
171 callback
.Run(result
);
174 void OnConfigureService(
175 const dbus::ObjectPath
& profile_path
,
176 const base::DictionaryValue
& properties
,
177 const ObjectPathCallback
& callback
,
178 const ShillClientHelper::ErrorCallback
& error_callback
) {
179 callback
.Run(dbus::ObjectPath("/service/2"));
182 void OnGetLoadableProfileEntries(
183 const dbus::ObjectPath
& service_path
,
184 const ShillClientHelper::DictionaryValueCallback
& callback
) {
185 base::DictionaryValue entries
;
186 entries
.SetString("profile1", "entry1");
187 entries
.SetString("profile2", "entry2");
188 callback
.Run(DBUS_METHOD_CALL_SUCCESS
, entries
);
191 void OnDeleteEntry(const dbus::ObjectPath
& profile_path
,
192 const std::string
& entry_path
,
193 const base::Closure
& callback
,
194 const ShillClientHelper::ErrorCallback
& error_callback
) {
195 // Don't run the callback immediately to emulate actual behavior.
196 message_loop_
.PostTask(FROM_HERE
, callback
);
199 bool PendingProfileEntryDeleterForTest(const std::string
& service_path
) {
200 return network_configuration_handler_
->
201 PendingProfileEntryDeleterForTest(service_path
);
205 MockShillManagerClient
* mock_manager_client_
;
206 MockShillProfileClient
* mock_profile_client_
;
207 MockShillServiceClient
* mock_service_client_
;
208 scoped_ptr
<NetworkStateHandler
> network_state_handler_
;
209 scoped_ptr
<NetworkConfigurationHandler
> network_configuration_handler_
;
210 base::MessageLoopForUI message_loop_
;
211 base::DictionaryValue
* dictionary_value_result_
;
214 TEST_F(NetworkConfigurationHandlerTest
, GetProperties
) {
215 std::string service_path
= "/service/1";
216 std::string expected_json
= "{\n \"SSID\": \"MyNetwork\"\n}\n";
217 std::string networkName
= "MyNetwork";
218 std::string key
= "SSID";
219 scoped_ptr
<base::StringValue
> networkNameValue(
220 base::Value::CreateStringValue(networkName
));
222 base::DictionaryValue value
;
223 value
.Set(key
, base::Value::CreateStringValue(networkName
));
224 dictionary_value_result_
= &value
;
225 EXPECT_CALL(*mock_service_client_
,
226 SetProperty(dbus::ObjectPath(service_path
), key
,
227 IsEqualTo(networkNameValue
.get()), _
, _
)).Times(1);
228 mock_service_client_
->SetProperty(dbus::ObjectPath(service_path
),
231 base::Bind(&base::DoNothing
),
232 base::Bind(&DBusErrorCallback
));
233 message_loop_
.RunUntilIdle();
235 ShillServiceClient::DictionaryValueCallback get_properties_callback
;
236 EXPECT_CALL(*mock_service_client_
,
237 GetProperties(_
, _
)).WillOnce(
239 &NetworkConfigurationHandlerTest::OnGetProperties
));
240 network_configuration_handler_
->GetProperties(
242 base::Bind(&DictionaryValueCallback
,
245 base::Bind(&ErrorCallback
, false, service_path
));
246 message_loop_
.RunUntilIdle();
249 TEST_F(NetworkConfigurationHandlerTest
, SetProperties
) {
250 std::string service_path
= "/service/1";
251 std::string networkName
= "MyNetwork";
252 std::string key
= "SSID";
253 scoped_ptr
<base::StringValue
> networkNameValue(
254 base::Value::CreateStringValue(networkName
));
256 base::DictionaryValue value
;
257 value
.Set(key
, base::Value::CreateStringValue(networkName
));
258 dictionary_value_result_
= &value
;
259 EXPECT_CALL(*mock_service_client_
,
260 SetProperties(_
, _
, _
, _
)).WillOnce(
262 &NetworkConfigurationHandlerTest::OnSetProperties
));
263 network_configuration_handler_
->SetProperties(
266 base::Bind(&base::DoNothing
),
267 base::Bind(&ErrorCallback
, false, service_path
));
268 message_loop_
.RunUntilIdle();
271 TEST_F(NetworkConfigurationHandlerTest
, ClearProperties
) {
272 std::string service_path
= "/service/1";
273 std::string networkName
= "MyNetwork";
274 std::string key
= "SSID";
275 scoped_ptr
<base::StringValue
> networkNameValue(
276 base::Value::CreateStringValue(networkName
));
278 // First set up a value to clear.
279 base::DictionaryValue value
;
280 value
.Set(key
, base::Value::CreateStringValue(networkName
));
281 dictionary_value_result_
= &value
;
282 EXPECT_CALL(*mock_service_client_
,
283 SetProperties(_
, _
, _
, _
)).WillOnce(
285 &NetworkConfigurationHandlerTest::OnSetProperties
));
286 network_configuration_handler_
->SetProperties(
289 base::Bind(&base::DoNothing
),
290 base::Bind(&ErrorCallback
, false, service_path
));
291 message_loop_
.RunUntilIdle();
294 std::vector
<std::string
> values_to_clear
;
295 values_to_clear
.push_back(key
);
296 EXPECT_CALL(*mock_service_client_
,
297 ClearProperties(_
, _
, _
, _
)).WillOnce(
299 &NetworkConfigurationHandlerTest::OnClearProperties
));
300 network_configuration_handler_
->ClearProperties(
303 base::Bind(&base::DoNothing
),
304 base::Bind(&ErrorCallback
, false, service_path
));
305 message_loop_
.RunUntilIdle();
308 TEST_F(NetworkConfigurationHandlerTest
, ClearPropertiesError
) {
309 std::string service_path
= "/service/1";
310 std::string networkName
= "MyNetwork";
311 std::string key
= "SSID";
312 scoped_ptr
<base::StringValue
> networkNameValue(
313 base::Value::CreateStringValue(networkName
));
315 // First set up a value to clear.
316 base::DictionaryValue value
;
317 value
.Set(key
, base::Value::CreateStringValue(networkName
));
318 dictionary_value_result_
= &value
;
319 EXPECT_CALL(*mock_service_client_
,
320 SetProperties(_
, _
, _
, _
)).WillOnce(
322 &NetworkConfigurationHandlerTest::OnSetProperties
));
323 network_configuration_handler_
->SetProperties(
326 base::Bind(&base::DoNothing
),
327 base::Bind(&ErrorCallback
, false, service_path
));
328 message_loop_
.RunUntilIdle();
331 std::vector
<std::string
> values_to_clear
;
332 values_to_clear
.push_back(key
);
334 *mock_service_client_
,
335 ClearProperties(_
, _
, _
, _
)).WillOnce(
337 &NetworkConfigurationHandlerTest::OnClearPropertiesError
));
338 network_configuration_handler_
->ClearProperties(
341 base::Bind(&base::DoNothing
),
342 base::Bind(&ErrorCallback
, true, service_path
));
343 message_loop_
.RunUntilIdle();
346 TEST_F(NetworkConfigurationHandlerTest
, CreateConfiguration
) {
347 std::string networkName
= "MyNetwork";
348 std::string key
= "SSID";
349 std::string profile
= "profile path";
350 base::DictionaryValue value
;
351 shill_property_util::SetSSID(networkName
, &value
);
352 value
.SetWithoutPathExpansion(shill::kProfileProperty
,
353 base::Value::CreateStringValue(profile
));
355 EXPECT_CALL(*mock_manager_client_
,
356 ConfigureServiceForProfile(dbus::ObjectPath(profile
), _
, _
, _
))
358 Invoke(this, &NetworkConfigurationHandlerTest::OnConfigureService
));
359 network_configuration_handler_
->CreateConfiguration(
361 base::Bind(&StringResultCallback
, std::string("/service/2")),
362 base::Bind(&ErrorCallback
, false, std::string()));
363 message_loop_
.RunUntilIdle();
366 TEST_F(NetworkConfigurationHandlerTest
, RemoveConfiguration
) {
367 std::string service_path
= "/service/1";
369 TestCallback test_callback
;
371 *mock_service_client_
,
372 GetLoadableProfileEntries(_
, _
)).WillOnce(Invoke(
374 &NetworkConfigurationHandlerTest::OnGetLoadableProfileEntries
));
376 *mock_profile_client_
,
377 DeleteEntry(_
, _
, _
, _
)).WillRepeatedly(Invoke(
379 &NetworkConfigurationHandlerTest::OnDeleteEntry
));
381 network_configuration_handler_
->RemoveConfiguration(
383 base::Bind(&TestCallback::Run
, base::Unretained(&test_callback
)),
384 base::Bind(&ErrorCallback
, false, service_path
));
385 message_loop_
.RunUntilIdle();
386 EXPECT_EQ(1, test_callback
.run_count());
387 EXPECT_FALSE(PendingProfileEntryDeleterForTest(service_path
));
390 ////////////////////////////////////////////////////////////////////////////////
395 class TestObserver
: public chromeos::NetworkStateHandlerObserver
{
397 TestObserver() : network_list_changed_count_(0) {}
398 virtual ~TestObserver() {}
400 virtual void NetworkListChanged() OVERRIDE
{
401 ++network_list_changed_count_
;
404 virtual void NetworkPropertiesUpdated(const NetworkState
* network
) OVERRIDE
{
405 property_updates_
[network
->path()]++;
408 size_t network_list_changed_count() { return network_list_changed_count_
; }
410 int PropertyUpdatesForService(const std::string
& service_path
) {
411 return property_updates_
[service_path
];
414 void ClearPropertyUpdates() {
415 property_updates_
.clear();
419 size_t network_list_changed_count_
;
420 std::map
<std::string
, int> property_updates_
;
422 DISALLOW_COPY_AND_ASSIGN(TestObserver
);
427 class NetworkConfigurationHandlerStubTest
: public testing::Test
{
429 NetworkConfigurationHandlerStubTest() {
432 virtual ~NetworkConfigurationHandlerStubTest() {
435 virtual void SetUp() OVERRIDE
{
436 DBusThreadManager::InitializeWithStub();
438 network_state_handler_
.reset(NetworkStateHandler::InitializeForTest());
439 test_observer_
.reset(new TestObserver());
440 network_state_handler_
->AddObserver(test_observer_
.get(), FROM_HERE
);
442 network_configuration_handler_
.reset(new NetworkConfigurationHandler());
443 network_configuration_handler_
->Init(network_state_handler_
.get());
445 message_loop_
.RunUntilIdle();
446 test_observer_
->ClearPropertyUpdates();
449 virtual void TearDown() OVERRIDE
{
450 network_configuration_handler_
.reset();
451 network_state_handler_
->RemoveObserver(test_observer_
.get(), FROM_HERE
);
452 network_state_handler_
.reset();
453 DBusThreadManager::Shutdown();
456 void SuccessCallback(const std::string
& callback_name
) {
457 success_callback_name_
= callback_name
;
460 void GetPropertiesCallback(const std::string
& service_path
,
461 const base::DictionaryValue
& dictionary
) {
462 get_properties_path_
= service_path
;
463 get_properties_
.reset(dictionary
.DeepCopy());
466 void CreateConfigurationCallback(const std::string
& service_path
) {
467 create_service_path_
= service_path
;
471 bool GetServiceStringProperty(const std::string
& service_path
,
472 const std::string
& key
,
473 std::string
* result
) {
474 ShillServiceClient::TestInterface
* service_test
=
475 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
476 const base::DictionaryValue
* properties
=
477 service_test
->GetServiceProperties(service_path
);
478 if (properties
&& properties
->GetStringWithoutPathExpansion(key
, result
))
483 bool GetReceivedStringProperty(const std::string
& service_path
,
484 const std::string
& key
,
485 std::string
* result
) {
486 if (get_properties_path_
!= service_path
)
488 if (get_properties_
&&
489 get_properties_
->GetStringWithoutPathExpansion(key
, result
))
494 scoped_ptr
<NetworkStateHandler
> network_state_handler_
;
495 scoped_ptr
<NetworkConfigurationHandler
> network_configuration_handler_
;
496 scoped_ptr
<TestObserver
> test_observer_
;
497 base::MessageLoopForUI message_loop_
;
498 std::string success_callback_name_
;
499 std::string get_properties_path_
;
500 scoped_ptr
<base::DictionaryValue
> get_properties_
;
501 std::string create_service_path_
;
504 TEST_F(NetworkConfigurationHandlerStubTest
, StubSetAndClearProperties
) {
505 // TODO(stevenjb): Remove dependency on default Stub service.
506 const std::string
service_path("wifi1");
507 const std::string
test_identity("test_identity");
508 const std::string
test_passphrase("test_passphrase");
511 base::DictionaryValue properties_to_set
;
512 properties_to_set
.SetStringWithoutPathExpansion(
513 shill::kIdentityProperty
, test_identity
);
514 properties_to_set
.SetStringWithoutPathExpansion(
515 shill::kPassphraseProperty
, test_passphrase
);
516 network_configuration_handler_
->SetProperties(
520 &NetworkConfigurationHandlerStubTest::SuccessCallback
,
521 base::Unretained(this), "SetProperties"),
522 base::Bind(&ErrorCallback
, false, service_path
));
523 message_loop_
.RunUntilIdle();
525 EXPECT_EQ("SetProperties", success_callback_name_
);
526 std::string identity
, passphrase
;
527 EXPECT_TRUE(GetServiceStringProperty(
528 service_path
, shill::kIdentityProperty
, &identity
));
529 EXPECT_TRUE(GetServiceStringProperty(
530 service_path
, shill::kPassphraseProperty
, &passphrase
));
531 EXPECT_EQ(test_identity
, identity
);
532 EXPECT_EQ(test_passphrase
, passphrase
);
533 EXPECT_EQ(1, test_observer_
->PropertyUpdatesForService(service_path
));
536 std::vector
<std::string
> properties_to_clear
;
537 properties_to_clear
.push_back(shill::kIdentityProperty
);
538 properties_to_clear
.push_back(shill::kPassphraseProperty
);
539 network_configuration_handler_
->ClearProperties(
543 &NetworkConfigurationHandlerStubTest::SuccessCallback
,
544 base::Unretained(this), "ClearProperties"),
545 base::Bind(&ErrorCallback
, false, service_path
));
546 message_loop_
.RunUntilIdle();
548 EXPECT_EQ("ClearProperties", success_callback_name_
);
549 EXPECT_FALSE(GetServiceStringProperty(
550 service_path
, shill::kIdentityProperty
, &identity
));
551 EXPECT_FALSE(GetServiceStringProperty(
552 service_path
, shill::kIdentityProperty
, &passphrase
));
553 EXPECT_EQ(2, test_observer_
->PropertyUpdatesForService(service_path
));
556 TEST_F(NetworkConfigurationHandlerStubTest
, StubGetNameFromWifiHex
) {
557 // TODO(stevenjb): Remove dependency on default Stub service.
558 const std::string
service_path("wifi1");
559 std::string wifi_hex
= "5468697320697320484558205353494421";
560 std::string expected_name
= "This is HEX SSID!";
563 base::DictionaryValue properties_to_set
;
564 properties_to_set
.SetStringWithoutPathExpansion(
565 shill::kWifiHexSsid
, wifi_hex
);
566 network_configuration_handler_
->SetProperties(
569 base::Bind(&base::DoNothing
),
570 base::Bind(&ErrorCallback
, false, service_path
));
571 message_loop_
.RunUntilIdle();
572 std::string wifi_hex_result
;
573 EXPECT_TRUE(GetServiceStringProperty(
574 service_path
, shill::kWifiHexSsid
, &wifi_hex_result
));
575 EXPECT_EQ(wifi_hex
, wifi_hex_result
);
578 network_configuration_handler_
->GetProperties(
580 base::Bind(&NetworkConfigurationHandlerStubTest::GetPropertiesCallback
,
581 base::Unretained(this)),
582 base::Bind(&ErrorCallback
, false, service_path
));
583 message_loop_
.RunUntilIdle();
585 EXPECT_EQ(service_path
, get_properties_path_
);
586 std::string name_result
;
587 EXPECT_TRUE(GetReceivedStringProperty(
588 service_path
, shill::kNameProperty
, &name_result
));
589 EXPECT_EQ(expected_name
, name_result
);
592 TEST_F(NetworkConfigurationHandlerStubTest
, StubCreateConfiguration
) {
593 const std::string
service_path("test_wifi");
594 base::DictionaryValue properties
;
595 shill_property_util::SetSSID(service_path
, &properties
);
596 properties
.SetStringWithoutPathExpansion(shill::kNameProperty
, service_path
);
597 properties
.SetStringWithoutPathExpansion(shill::kGuidProperty
, service_path
);
598 properties
.SetStringWithoutPathExpansion(
599 shill::kTypeProperty
, shill::kTypeWifi
);
600 properties
.SetStringWithoutPathExpansion(
601 shill::kStateProperty
, shill::kStateIdle
);
602 properties
.SetStringWithoutPathExpansion(
603 shill::kProfileProperty
, shill_stub_helper::kSharedProfilePath
);
605 network_configuration_handler_
->CreateConfiguration(
608 &NetworkConfigurationHandlerStubTest::CreateConfigurationCallback
,
609 base::Unretained(this)),
610 base::Bind(&ErrorCallback
, false, service_path
));
611 message_loop_
.RunUntilIdle();
613 EXPECT_FALSE(create_service_path_
.empty());
616 EXPECT_TRUE(GetServiceStringProperty(
617 create_service_path_
, shill::kGuidProperty
, &guid
));
618 EXPECT_EQ(service_path
, guid
);
620 std::string actual_profile
;
621 EXPECT_TRUE(GetServiceStringProperty(
622 create_service_path_
, shill::kProfileProperty
, &actual_profile
));
623 EXPECT_EQ(shill_stub_helper::kSharedProfilePath
, actual_profile
);
626 } // namespace chromeos