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/mock_shill_manager_client.h"
12 #include "chromeos/dbus/mock_shill_profile_client.h"
13 #include "chromeos/dbus/mock_shill_service_client.h"
14 #include "chromeos/network/network_configuration_handler.h"
15 #include "chromeos/network/network_profile_handler.h"
16 #include "chromeos/network/network_state.h"
17 #include "chromeos/network/network_state_handler.h"
18 #include "chromeos/network/network_state_handler_observer.h"
19 #include "chromeos/network/shill_property_util.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "third_party/cros_system_api/dbus/service_constants.h"
25 using ::testing::AnyNumber;
26 using ::testing::Invoke;
27 using ::testing::Pointee;
28 using ::testing::Return;
29 using ::testing::SaveArg;
30 using ::testing::StrEq;
32 // Matcher to match base::Value.
33 MATCHER_P(IsEqualTo, value, "") { return arg.Equals(value); }
39 static std::string PrettyJson(const base::DictionaryValue& value) {
41 base::JSONWriter::WriteWithOptions(&value,
42 base::JSONWriter::OPTIONS_PRETTY_PRINT,
47 void DictionaryValueCallback(
48 const std::string& expected_id,
49 const std::string& expected_json,
50 const std::string& service_path,
51 const base::DictionaryValue& dictionary) {
52 std::string dict_str = PrettyJson(dictionary);
53 EXPECT_EQ(expected_json, dict_str);
54 EXPECT_EQ(expected_id, service_path);
57 void ErrorCallback(bool error_expected,
58 const std::string& expected_id,
59 const std::string& error_name,
60 scoped_ptr<base::DictionaryValue> error_data) {
61 EXPECT_TRUE(error_expected) << "Unexpected error: " << error_name
62 << " with associated data: \n"
63 << PrettyJson(*error_data);
66 void StringResultCallback(const std::string& expected_result,
67 const std::string& result) {
68 EXPECT_EQ(expected_result, result);
71 void DBusErrorCallback(const std::string& error_name,
72 const std::string& error_message) {
73 EXPECT_TRUE(false) << "DBus Error: " << error_name << "("
74 << error_message << ")";
79 TestCallback() : run_count_(0) {}
83 int run_count() const { return run_count_; }
91 class NetworkConfigurationHandlerTest : public testing::Test {
93 NetworkConfigurationHandlerTest()
94 : mock_manager_client_(NULL),
95 mock_profile_client_(NULL),
96 mock_service_client_(NULL),
97 dictionary_value_result_(NULL) {}
98 virtual ~NetworkConfigurationHandlerTest() {}
100 virtual void SetUp() override {
101 scoped_ptr<DBusThreadManagerSetter> dbus_setter =
102 DBusThreadManager::GetSetterForTesting();
103 mock_manager_client_ = new MockShillManagerClient();
104 mock_profile_client_ = new MockShillProfileClient();
105 mock_service_client_ = new MockShillServiceClient();
106 dbus_setter->SetShillManagerClient(
107 scoped_ptr<ShillManagerClient>(mock_manager_client_).Pass());
108 dbus_setter->SetShillProfileClient(
109 scoped_ptr<ShillProfileClient>(mock_profile_client_).Pass());
110 dbus_setter->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 network_state_handler_.reset(NetworkStateHandler::InitializeForTest());
123 network_configuration_handler_.reset(new NetworkConfigurationHandler());
124 network_configuration_handler_->Init(network_state_handler_.get());
125 message_loop_.RunUntilIdle();
128 virtual void TearDown() override {
129 network_configuration_handler_.reset();
130 network_state_handler_.reset();
131 DBusThreadManager::Shutdown();
134 // Handles responses for GetProperties method calls.
135 void OnGetProperties(
136 const dbus::ObjectPath& path,
137 const ShillClientHelper::DictionaryValueCallback& callback) {
138 callback.Run(DBUS_METHOD_CALL_SUCCESS, *dictionary_value_result_);
141 // Handles responses for SetProperties method calls.
142 void OnSetProperties(const dbus::ObjectPath& service_path,
143 const base::DictionaryValue& properties,
144 const base::Closure& callback,
145 const ShillClientHelper::ErrorCallback& error_callback) {
149 // Handles responses for ClearProperties method calls.
150 void OnClearProperties(
151 const dbus::ObjectPath& service_path,
152 const std::vector<std::string>& names,
153 const ShillClientHelper::ListValueCallback& callback,
154 const ShillClientHelper::ErrorCallback& error_callback) {
155 base::ListValue result;
156 result.AppendBoolean(true);
157 callback.Run(result);
160 // Handles responses for ClearProperties method calls, and simulates an error
162 void OnClearPropertiesError(
163 const dbus::ObjectPath& service_path,
164 const std::vector<std::string>& names,
165 const ShillClientHelper::ListValueCallback& callback,
166 const ShillClientHelper::ErrorCallback& error_callback) {
167 base::ListValue result;
168 result.AppendBoolean(false);
169 callback.Run(result);
172 void OnConfigureService(
173 const dbus::ObjectPath& profile_path,
174 const base::DictionaryValue& properties,
175 const ObjectPathCallback& callback,
176 const ShillClientHelper::ErrorCallback& error_callback) {
177 callback.Run(dbus::ObjectPath("/service/2"));
180 void OnGetLoadableProfileEntries(
181 const dbus::ObjectPath& service_path,
182 const ShillClientHelper::DictionaryValueCallback& callback) {
183 base::DictionaryValue entries;
184 entries.SetString("profile1", "entry1");
185 entries.SetString("profile2", "entry2");
186 callback.Run(DBUS_METHOD_CALL_SUCCESS, entries);
189 void OnDeleteEntry(const dbus::ObjectPath& profile_path,
190 const std::string& entry_path,
191 const base::Closure& callback,
192 const ShillClientHelper::ErrorCallback& error_callback) {
193 // Don't run the callback immediately to emulate actual behavior.
194 message_loop_.PostTask(FROM_HERE, callback);
197 bool PendingProfileEntryDeleterForTest(const std::string& service_path) {
198 return network_configuration_handler_->
199 PendingProfileEntryDeleterForTest(service_path);
203 MockShillManagerClient* mock_manager_client_;
204 MockShillProfileClient* mock_profile_client_;
205 MockShillServiceClient* mock_service_client_;
206 scoped_ptr<NetworkStateHandler> network_state_handler_;
207 scoped_ptr<NetworkConfigurationHandler> network_configuration_handler_;
208 base::MessageLoopForUI message_loop_;
209 base::DictionaryValue* dictionary_value_result_;
212 TEST_F(NetworkConfigurationHandlerTest, GetProperties) {
213 std::string service_path = "/service/1";
214 std::string expected_json = "{\n \"SSID\": \"MyNetwork\"\n}\n";
215 std::string networkName = "MyNetwork";
216 std::string key = "SSID";
217 scoped_ptr<base::StringValue> networkNameValue(
218 new base::StringValue(networkName));
220 base::DictionaryValue value;
221 value.Set(key, new base::StringValue(networkName));
222 dictionary_value_result_ = &value;
223 EXPECT_CALL(*mock_service_client_,
224 SetProperty(dbus::ObjectPath(service_path), key,
225 IsEqualTo(networkNameValue.get()), _, _)).Times(1);
226 mock_service_client_->SetProperty(dbus::ObjectPath(service_path),
229 base::Bind(&base::DoNothing),
230 base::Bind(&DBusErrorCallback));
231 message_loop_.RunUntilIdle();
233 ShillServiceClient::DictionaryValueCallback get_properties_callback;
234 EXPECT_CALL(*mock_service_client_,
235 GetProperties(_, _)).WillOnce(
237 &NetworkConfigurationHandlerTest::OnGetProperties));
238 network_configuration_handler_->GetProperties(
240 base::Bind(&DictionaryValueCallback,
243 base::Bind(&ErrorCallback, false, service_path));
244 message_loop_.RunUntilIdle();
247 TEST_F(NetworkConfigurationHandlerTest, SetProperties) {
248 std::string service_path = "/service/1";
249 std::string networkName = "MyNetwork";
250 std::string key = "SSID";
251 scoped_ptr<base::StringValue> networkNameValue(
252 new base::StringValue(networkName));
254 base::DictionaryValue value;
255 value.Set(key, new base::StringValue(networkName));
256 dictionary_value_result_ = &value;
257 EXPECT_CALL(*mock_service_client_,
258 SetProperties(_, _, _, _)).WillOnce(
260 &NetworkConfigurationHandlerTest::OnSetProperties));
261 network_configuration_handler_->SetProperties(
264 base::Bind(&base::DoNothing),
265 base::Bind(&ErrorCallback, false, service_path));
266 message_loop_.RunUntilIdle();
269 TEST_F(NetworkConfigurationHandlerTest, ClearProperties) {
270 std::string service_path = "/service/1";
271 std::string networkName = "MyNetwork";
272 std::string key = "SSID";
273 scoped_ptr<base::StringValue> networkNameValue(
274 new base::StringValue(networkName));
276 // First set up a value to clear.
277 base::DictionaryValue value;
278 value.Set(key, new base::StringValue(networkName));
279 dictionary_value_result_ = &value;
280 EXPECT_CALL(*mock_service_client_,
281 SetProperties(_, _, _, _)).WillOnce(
283 &NetworkConfigurationHandlerTest::OnSetProperties));
284 network_configuration_handler_->SetProperties(
287 base::Bind(&base::DoNothing),
288 base::Bind(&ErrorCallback, false, service_path));
289 message_loop_.RunUntilIdle();
292 std::vector<std::string> values_to_clear;
293 values_to_clear.push_back(key);
294 EXPECT_CALL(*mock_service_client_,
295 ClearProperties(_, _, _, _)).WillOnce(
297 &NetworkConfigurationHandlerTest::OnClearProperties));
298 network_configuration_handler_->ClearProperties(
301 base::Bind(&base::DoNothing),
302 base::Bind(&ErrorCallback, false, service_path));
303 message_loop_.RunUntilIdle();
306 TEST_F(NetworkConfigurationHandlerTest, ClearPropertiesError) {
307 std::string service_path = "/service/1";
308 std::string networkName = "MyNetwork";
309 std::string key = "SSID";
310 scoped_ptr<base::StringValue> networkNameValue(
311 new base::StringValue(networkName));
313 // First set up a value to clear.
314 base::DictionaryValue value;
315 value.Set(key, new base::StringValue(networkName));
316 dictionary_value_result_ = &value;
317 EXPECT_CALL(*mock_service_client_,
318 SetProperties(_, _, _, _)).WillOnce(
320 &NetworkConfigurationHandlerTest::OnSetProperties));
321 network_configuration_handler_->SetProperties(
324 base::Bind(&base::DoNothing),
325 base::Bind(&ErrorCallback, false, service_path));
326 message_loop_.RunUntilIdle();
329 std::vector<std::string> values_to_clear;
330 values_to_clear.push_back(key);
332 *mock_service_client_,
333 ClearProperties(_, _, _, _)).WillOnce(
335 &NetworkConfigurationHandlerTest::OnClearPropertiesError));
336 network_configuration_handler_->ClearProperties(
339 base::Bind(&base::DoNothing),
340 base::Bind(&ErrorCallback, true, service_path));
341 message_loop_.RunUntilIdle();
344 TEST_F(NetworkConfigurationHandlerTest, CreateConfiguration) {
345 std::string networkName = "MyNetwork";
346 std::string key = "SSID";
347 std::string type = "wifi";
348 std::string profile = "profile path";
349 base::DictionaryValue value;
350 shill_property_util::SetSSID(networkName, &value);
351 value.SetWithoutPathExpansion(shill::kTypeProperty,
352 new base::StringValue(type));
353 value.SetWithoutPathExpansion(shill::kProfileProperty,
354 new base::StringValue(profile));
356 EXPECT_CALL(*mock_manager_client_,
357 ConfigureServiceForProfile(dbus::ObjectPath(profile), _, _, _))
359 Invoke(this, &NetworkConfigurationHandlerTest::OnConfigureService));
360 network_configuration_handler_->CreateConfiguration(
362 base::Bind(&StringResultCallback, std::string("/service/2")),
363 base::Bind(&ErrorCallback, false, std::string()));
364 message_loop_.RunUntilIdle();
367 TEST_F(NetworkConfigurationHandlerTest, RemoveConfiguration) {
368 std::string service_path = "/service/1";
370 TestCallback test_callback;
372 *mock_service_client_,
373 GetLoadableProfileEntries(_, _)).WillOnce(Invoke(
375 &NetworkConfigurationHandlerTest::OnGetLoadableProfileEntries));
377 *mock_profile_client_,
378 DeleteEntry(_, _, _, _)).WillRepeatedly(Invoke(
380 &NetworkConfigurationHandlerTest::OnDeleteEntry));
382 network_configuration_handler_->RemoveConfiguration(
384 base::Bind(&TestCallback::Run, base::Unretained(&test_callback)),
385 base::Bind(&ErrorCallback, false, service_path));
386 message_loop_.RunUntilIdle();
387 EXPECT_EQ(1, test_callback.run_count());
388 EXPECT_FALSE(PendingProfileEntryDeleterForTest(service_path));
391 ////////////////////////////////////////////////////////////////////////////////
396 class TestObserver : public chromeos::NetworkStateHandlerObserver {
398 TestObserver() : network_list_changed_count_(0) {}
399 virtual ~TestObserver() {}
401 virtual void NetworkListChanged() override {
402 ++network_list_changed_count_;
405 virtual void NetworkPropertiesUpdated(const NetworkState* network) override {
406 property_updates_[network->path()]++;
409 size_t network_list_changed_count() { return network_list_changed_count_; }
411 int PropertyUpdatesForService(const std::string& service_path) {
412 return property_updates_[service_path];
415 void ClearPropertyUpdates() {
416 property_updates_.clear();
420 size_t network_list_changed_count_;
421 std::map<std::string, int> property_updates_;
423 DISALLOW_COPY_AND_ASSIGN(TestObserver);
428 class NetworkConfigurationHandlerStubTest : public testing::Test {
430 NetworkConfigurationHandlerStubTest() {
433 virtual ~NetworkConfigurationHandlerStubTest() {
436 virtual void SetUp() override {
437 DBusThreadManager::Initialize();
439 network_state_handler_.reset(NetworkStateHandler::InitializeForTest());
440 test_observer_.reset(new TestObserver());
441 network_state_handler_->AddObserver(test_observer_.get(), FROM_HERE);
443 network_configuration_handler_.reset(new NetworkConfigurationHandler());
444 network_configuration_handler_->Init(network_state_handler_.get());
446 message_loop_.RunUntilIdle();
447 test_observer_->ClearPropertyUpdates();
450 virtual void TearDown() override {
451 network_configuration_handler_.reset();
452 network_state_handler_->RemoveObserver(test_observer_.get(), FROM_HERE);
453 network_state_handler_.reset();
454 DBusThreadManager::Shutdown();
457 void SuccessCallback(const std::string& callback_name) {
458 success_callback_name_ = callback_name;
461 void GetPropertiesCallback(const std::string& service_path,
462 const base::DictionaryValue& dictionary) {
463 get_properties_path_ = service_path;
464 get_properties_.reset(dictionary.DeepCopy());
467 void CreateConfigurationCallback(const std::string& service_path) {
468 create_service_path_ = service_path;
472 bool GetServiceStringProperty(const std::string& service_path,
473 const std::string& key,
474 std::string* result) {
475 ShillServiceClient::TestInterface* service_test =
476 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
477 const base::DictionaryValue* properties =
478 service_test->GetServiceProperties(service_path);
479 if (properties && properties->GetStringWithoutPathExpansion(key, result))
484 bool GetReceivedStringProperty(const std::string& service_path,
485 const std::string& key,
486 std::string* result) {
487 if (get_properties_path_ != service_path)
489 if (get_properties_ &&
490 get_properties_->GetStringWithoutPathExpansion(key, result))
495 scoped_ptr<NetworkStateHandler> network_state_handler_;
496 scoped_ptr<NetworkConfigurationHandler> network_configuration_handler_;
497 scoped_ptr<TestObserver> test_observer_;
498 base::MessageLoopForUI message_loop_;
499 std::string success_callback_name_;
500 std::string get_properties_path_;
501 scoped_ptr<base::DictionaryValue> get_properties_;
502 std::string create_service_path_;
505 TEST_F(NetworkConfigurationHandlerStubTest, StubSetAndClearProperties) {
506 // TODO(stevenjb): Remove dependency on default Stub service.
507 const std::string service_path("/service/wifi1");
508 const std::string test_identity("test_identity");
509 const std::string test_passphrase("test_passphrase");
512 base::DictionaryValue properties_to_set;
513 properties_to_set.SetStringWithoutPathExpansion(
514 shill::kIdentityProperty, test_identity);
515 properties_to_set.SetStringWithoutPathExpansion(
516 shill::kPassphraseProperty, test_passphrase);
517 network_configuration_handler_->SetProperties(
521 &NetworkConfigurationHandlerStubTest::SuccessCallback,
522 base::Unretained(this), "SetProperties"),
523 base::Bind(&ErrorCallback, false, service_path));
524 message_loop_.RunUntilIdle();
526 EXPECT_EQ("SetProperties", success_callback_name_);
527 std::string identity, passphrase;
528 EXPECT_TRUE(GetServiceStringProperty(
529 service_path, shill::kIdentityProperty, &identity));
530 EXPECT_TRUE(GetServiceStringProperty(
531 service_path, shill::kPassphraseProperty, &passphrase));
532 EXPECT_EQ(test_identity, identity);
533 EXPECT_EQ(test_passphrase, passphrase);
534 EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(service_path));
537 std::vector<std::string> properties_to_clear;
538 properties_to_clear.push_back(shill::kIdentityProperty);
539 properties_to_clear.push_back(shill::kPassphraseProperty);
540 network_configuration_handler_->ClearProperties(
544 &NetworkConfigurationHandlerStubTest::SuccessCallback,
545 base::Unretained(this), "ClearProperties"),
546 base::Bind(&ErrorCallback, false, service_path));
547 message_loop_.RunUntilIdle();
549 EXPECT_EQ("ClearProperties", success_callback_name_);
550 EXPECT_FALSE(GetServiceStringProperty(
551 service_path, shill::kIdentityProperty, &identity));
552 EXPECT_FALSE(GetServiceStringProperty(
553 service_path, shill::kIdentityProperty, &passphrase));
554 EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(service_path));
557 TEST_F(NetworkConfigurationHandlerStubTest, StubGetNameFromWifiHex) {
558 // TODO(stevenjb): Remove dependency on default Stub service.
559 const std::string service_path("/service/wifi1");
560 std::string wifi_hex = "5468697320697320484558205353494421";
561 std::string expected_name = "This is HEX SSID!";
564 base::DictionaryValue properties_to_set;
565 properties_to_set.SetStringWithoutPathExpansion(
566 shill::kWifiHexSsid, wifi_hex);
567 network_configuration_handler_->SetProperties(
570 base::Bind(&base::DoNothing),
571 base::Bind(&ErrorCallback, false, service_path));
572 message_loop_.RunUntilIdle();
573 std::string wifi_hex_result;
574 EXPECT_TRUE(GetServiceStringProperty(
575 service_path, shill::kWifiHexSsid, &wifi_hex_result));
576 EXPECT_EQ(wifi_hex, wifi_hex_result);
579 network_configuration_handler_->GetProperties(
581 base::Bind(&NetworkConfigurationHandlerStubTest::GetPropertiesCallback,
582 base::Unretained(this)),
583 base::Bind(&ErrorCallback, false, service_path));
584 message_loop_.RunUntilIdle();
586 EXPECT_EQ(service_path, get_properties_path_);
587 std::string name_result;
588 EXPECT_TRUE(GetReceivedStringProperty(
589 service_path, shill::kNameProperty, &name_result));
590 EXPECT_EQ(expected_name, name_result);
593 TEST_F(NetworkConfigurationHandlerStubTest, StubCreateConfiguration) {
594 const std::string service_path("/service/test_wifi");
595 base::DictionaryValue properties;
596 shill_property_util::SetSSID(service_path, &properties);
597 properties.SetStringWithoutPathExpansion(shill::kNameProperty, service_path);
598 properties.SetStringWithoutPathExpansion(shill::kGuidProperty, service_path);
599 properties.SetStringWithoutPathExpansion(
600 shill::kTypeProperty, shill::kTypeWifi);
601 properties.SetStringWithoutPathExpansion(
602 shill::kStateProperty, shill::kStateIdle);
603 properties.SetStringWithoutPathExpansion(
604 shill::kProfileProperty, NetworkProfileHandler::GetSharedProfilePath());
606 network_configuration_handler_->CreateConfiguration(
609 &NetworkConfigurationHandlerStubTest::CreateConfigurationCallback,
610 base::Unretained(this)),
611 base::Bind(&ErrorCallback, false, service_path));
612 message_loop_.RunUntilIdle();
614 EXPECT_FALSE(create_service_path_.empty());
617 EXPECT_TRUE(GetServiceStringProperty(
618 create_service_path_, shill::kGuidProperty, &guid));
619 EXPECT_EQ(service_path, guid);
621 std::string actual_profile;
622 EXPECT_TRUE(GetServiceStringProperty(
623 create_service_path_, shill::kProfileProperty, &actual_profile));
624 EXPECT_EQ(NetworkProfileHandler::GetSharedProfilePath(), actual_profile);
627 } // namespace chromeos