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_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::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 MockDBusThreadManager* mock_dbus_thread_manager = new MockDBusThreadManager;
102 EXPECT_CALL(*mock_dbus_thread_manager, GetSystemBus())
103 .WillRepeatedly(Return(reinterpret_cast<dbus::Bus*>(NULL)));
104 DBusThreadManager::InitializeForTesting(mock_dbus_thread_manager);
105 mock_manager_client_ =
106 mock_dbus_thread_manager->mock_shill_manager_client();
107 mock_profile_client_ =
108 mock_dbus_thread_manager->mock_shill_profile_client();
109 mock_service_client_ =
110 mock_dbus_thread_manager->mock_shill_service_client();
112 network_state_handler_.reset(NetworkStateHandler::InitializeForTest());
113 network_configuration_handler_.reset(new NetworkConfigurationHandler());
114 network_configuration_handler_->Init(network_state_handler_.get());
115 message_loop_.RunUntilIdle();
118 virtual void TearDown() OVERRIDE {
119 network_configuration_handler_.reset();
120 network_state_handler_.reset();
121 DBusThreadManager::Shutdown();
124 // Handles responses for GetProperties method calls.
125 void OnGetProperties(
126 const dbus::ObjectPath& path,
127 const ShillClientHelper::DictionaryValueCallback& callback) {
128 callback.Run(DBUS_METHOD_CALL_SUCCESS, *dictionary_value_result_);
131 // Handles responses for SetProperties method calls.
132 void OnSetProperties(const dbus::ObjectPath& service_path,
133 const base::DictionaryValue& properties,
134 const base::Closure& callback,
135 const ShillClientHelper::ErrorCallback& error_callback) {
139 // Handles responses for ClearProperties method calls.
140 void OnClearProperties(
141 const dbus::ObjectPath& service_path,
142 const std::vector<std::string>& names,
143 const ShillClientHelper::ListValueCallback& callback,
144 const ShillClientHelper::ErrorCallback& error_callback) {
145 base::ListValue result;
146 result.AppendBoolean(true);
147 callback.Run(result);
150 // Handles responses for ClearProperties method calls, and simulates an error
152 void OnClearPropertiesError(
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(false);
159 callback.Run(result);
162 void OnConfigureService(
163 const dbus::ObjectPath& profile_path,
164 const base::DictionaryValue& properties,
165 const ObjectPathCallback& callback,
166 const ShillClientHelper::ErrorCallback& error_callback) {
167 callback.Run(dbus::ObjectPath("/service/2"));
170 void OnGetLoadableProfileEntries(
171 const dbus::ObjectPath& service_path,
172 const ShillClientHelper::DictionaryValueCallback& callback) {
173 base::DictionaryValue entries;
174 entries.SetString("profile1", "entry1");
175 entries.SetString("profile2", "entry2");
176 callback.Run(DBUS_METHOD_CALL_SUCCESS, entries);
179 void OnDeleteEntry(const dbus::ObjectPath& profile_path,
180 const std::string& entry_path,
181 const base::Closure& callback,
182 const ShillClientHelper::ErrorCallback& error_callback) {
183 // Don't run the callback immediately to emulate actual behavior.
184 message_loop_.PostTask(FROM_HERE, callback);
187 bool PendingProfileEntryDeleterForTest(const std::string& service_path) {
188 return network_configuration_handler_->
189 PendingProfileEntryDeleterForTest(service_path);
193 MockShillManagerClient* mock_manager_client_;
194 MockShillProfileClient* mock_profile_client_;
195 MockShillServiceClient* mock_service_client_;
196 scoped_ptr<NetworkStateHandler> network_state_handler_;
197 scoped_ptr<NetworkConfigurationHandler> network_configuration_handler_;
198 base::MessageLoopForUI message_loop_;
199 base::DictionaryValue* dictionary_value_result_;
202 TEST_F(NetworkConfigurationHandlerTest, GetProperties) {
203 std::string service_path = "/service/1";
204 std::string expected_json = "{\n \"SSID\": \"MyNetwork\"\n}\n";
205 std::string networkName = "MyNetwork";
206 std::string key = "SSID";
207 scoped_ptr<base::StringValue> networkNameValue(
208 base::Value::CreateStringValue(networkName));
210 base::DictionaryValue value;
211 value.Set(key, base::Value::CreateStringValue(networkName));
212 dictionary_value_result_ = &value;
213 EXPECT_CALL(*mock_service_client_,
214 SetProperty(dbus::ObjectPath(service_path), key,
215 IsEqualTo(networkNameValue.get()), _, _)).Times(1);
216 DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
217 dbus::ObjectPath(service_path), key, *networkNameValue,
218 base::Bind(&base::DoNothing),
219 base::Bind(&DBusErrorCallback));
220 message_loop_.RunUntilIdle();
222 ShillServiceClient::DictionaryValueCallback get_properties_callback;
223 EXPECT_CALL(*mock_service_client_,
224 GetProperties(_, _)).WillOnce(
226 &NetworkConfigurationHandlerTest::OnGetProperties));
227 network_configuration_handler_->GetProperties(
229 base::Bind(&DictionaryValueCallback,
232 base::Bind(&ErrorCallback, false, service_path));
233 message_loop_.RunUntilIdle();
236 TEST_F(NetworkConfigurationHandlerTest, SetProperties) {
237 std::string service_path = "/service/1";
238 std::string networkName = "MyNetwork";
239 std::string key = "SSID";
240 scoped_ptr<base::StringValue> networkNameValue(
241 base::Value::CreateStringValue(networkName));
243 base::DictionaryValue value;
244 value.Set(key, base::Value::CreateStringValue(networkName));
245 dictionary_value_result_ = &value;
246 EXPECT_CALL(*mock_service_client_,
247 SetProperties(_, _, _, _)).WillOnce(
249 &NetworkConfigurationHandlerTest::OnSetProperties));
250 network_configuration_handler_->SetProperties(
253 base::Bind(&base::DoNothing),
254 base::Bind(&ErrorCallback, false, service_path));
255 message_loop_.RunUntilIdle();
258 TEST_F(NetworkConfigurationHandlerTest, ClearProperties) {
259 std::string service_path = "/service/1";
260 std::string networkName = "MyNetwork";
261 std::string key = "SSID";
262 scoped_ptr<base::StringValue> networkNameValue(
263 base::Value::CreateStringValue(networkName));
265 // First set up a value to clear.
266 base::DictionaryValue value;
267 value.Set(key, base::Value::CreateStringValue(networkName));
268 dictionary_value_result_ = &value;
269 EXPECT_CALL(*mock_service_client_,
270 SetProperties(_, _, _, _)).WillOnce(
272 &NetworkConfigurationHandlerTest::OnSetProperties));
273 network_configuration_handler_->SetProperties(
276 base::Bind(&base::DoNothing),
277 base::Bind(&ErrorCallback, false, service_path));
278 message_loop_.RunUntilIdle();
281 std::vector<std::string> values_to_clear;
282 values_to_clear.push_back(key);
283 EXPECT_CALL(*mock_service_client_,
284 ClearProperties(_, _, _, _)).WillOnce(
286 &NetworkConfigurationHandlerTest::OnClearProperties));
287 network_configuration_handler_->ClearProperties(
290 base::Bind(&base::DoNothing),
291 base::Bind(&ErrorCallback, false, service_path));
292 message_loop_.RunUntilIdle();
295 TEST_F(NetworkConfigurationHandlerTest, ClearPropertiesError) {
296 std::string service_path = "/service/1";
297 std::string networkName = "MyNetwork";
298 std::string key = "SSID";
299 scoped_ptr<base::StringValue> networkNameValue(
300 base::Value::CreateStringValue(networkName));
302 // First set up a value to clear.
303 base::DictionaryValue value;
304 value.Set(key, base::Value::CreateStringValue(networkName));
305 dictionary_value_result_ = &value;
306 EXPECT_CALL(*mock_service_client_,
307 SetProperties(_, _, _, _)).WillOnce(
309 &NetworkConfigurationHandlerTest::OnSetProperties));
310 network_configuration_handler_->SetProperties(
313 base::Bind(&base::DoNothing),
314 base::Bind(&ErrorCallback, false, service_path));
315 message_loop_.RunUntilIdle();
318 std::vector<std::string> values_to_clear;
319 values_to_clear.push_back(key);
321 *mock_service_client_,
322 ClearProperties(_, _, _, _)).WillOnce(
324 &NetworkConfigurationHandlerTest::OnClearPropertiesError));
325 network_configuration_handler_->ClearProperties(
328 base::Bind(&base::DoNothing),
329 base::Bind(&ErrorCallback, true, service_path));
330 message_loop_.RunUntilIdle();
333 TEST_F(NetworkConfigurationHandlerTest, CreateConfiguration) {
334 std::string networkName = "MyNetwork";
335 std::string key = "SSID";
336 std::string profile = "profile path";
337 base::DictionaryValue value;
338 shill_property_util::SetSSID(networkName, &value);
339 value.SetWithoutPathExpansion(shill::kProfileProperty,
340 base::Value::CreateStringValue(profile));
342 EXPECT_CALL(*mock_manager_client_,
343 ConfigureServiceForProfile(dbus::ObjectPath(profile), _, _, _))
345 Invoke(this, &NetworkConfigurationHandlerTest::OnConfigureService));
346 network_configuration_handler_->CreateConfiguration(
348 base::Bind(&StringResultCallback, std::string("/service/2")),
349 base::Bind(&ErrorCallback, false, std::string("")));
350 message_loop_.RunUntilIdle();
353 TEST_F(NetworkConfigurationHandlerTest, RemoveConfiguration) {
354 std::string service_path = "/service/1";
356 TestCallback test_callback;
358 *mock_service_client_,
359 GetLoadableProfileEntries(_, _)).WillOnce(Invoke(
361 &NetworkConfigurationHandlerTest::OnGetLoadableProfileEntries));
363 *mock_profile_client_,
364 DeleteEntry(_, _, _, _)).WillRepeatedly(Invoke(
366 &NetworkConfigurationHandlerTest::OnDeleteEntry));
368 network_configuration_handler_->RemoveConfiguration(
370 base::Bind(&TestCallback::Run, base::Unretained(&test_callback)),
371 base::Bind(&ErrorCallback, false, service_path));
372 message_loop_.RunUntilIdle();
373 EXPECT_EQ(1, test_callback.run_count());
374 EXPECT_FALSE(PendingProfileEntryDeleterForTest(service_path));
377 ////////////////////////////////////////////////////////////////////////////////
382 class TestObserver : public chromeos::NetworkStateHandlerObserver {
384 TestObserver() : network_list_changed_count_(0) {}
385 virtual ~TestObserver() {}
387 virtual void NetworkListChanged() OVERRIDE {
388 ++network_list_changed_count_;
391 virtual void NetworkPropertiesUpdated(const NetworkState* network) OVERRIDE {
392 property_updates_[network->path()]++;
395 size_t network_list_changed_count() { return network_list_changed_count_; }
397 int PropertyUpdatesForService(const std::string& service_path) {
398 return property_updates_[service_path];
401 void ClearPropertyUpdates() {
402 property_updates_.clear();
406 size_t network_list_changed_count_;
407 std::map<std::string, int> property_updates_;
409 DISALLOW_COPY_AND_ASSIGN(TestObserver);
414 class NetworkConfigurationHandlerStubTest : public testing::Test {
416 NetworkConfigurationHandlerStubTest() {
419 virtual ~NetworkConfigurationHandlerStubTest() {
422 virtual void SetUp() OVERRIDE {
423 DBusThreadManager::InitializeWithStub();
425 network_state_handler_.reset(NetworkStateHandler::InitializeForTest());
426 test_observer_.reset(new TestObserver());
427 network_state_handler_->AddObserver(test_observer_.get(), FROM_HERE);
429 network_configuration_handler_.reset(new NetworkConfigurationHandler());
430 network_configuration_handler_->Init(network_state_handler_.get());
432 message_loop_.RunUntilIdle();
433 test_observer_->ClearPropertyUpdates();
436 virtual void TearDown() OVERRIDE {
437 network_configuration_handler_.reset();
438 network_state_handler_->RemoveObserver(test_observer_.get(), FROM_HERE);
439 network_state_handler_.reset();
440 DBusThreadManager::Shutdown();
443 void SuccessCallback(const std::string& callback_name) {
444 success_callback_name_ = callback_name;
447 void GetPropertiesCallback(const std::string& service_path,
448 const base::DictionaryValue& dictionary) {
449 get_properties_path_ = service_path;
450 get_properties_.reset(dictionary.DeepCopy());
453 void CreateConfigurationCallback(const std::string& service_path) {
454 create_service_path_ = service_path;
458 bool GetServiceStringProperty(const std::string& service_path,
459 const std::string& key,
460 std::string* result) {
461 ShillServiceClient::TestInterface* service_test =
462 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
463 const base::DictionaryValue* properties =
464 service_test->GetServiceProperties(service_path);
465 if (properties && properties->GetStringWithoutPathExpansion(key, result))
470 bool GetReceivedStringProperty(const std::string& service_path,
471 const std::string& key,
472 std::string* result) {
473 if (get_properties_path_ != service_path)
475 if (get_properties_ &&
476 get_properties_->GetStringWithoutPathExpansion(key, result))
481 scoped_ptr<NetworkStateHandler> network_state_handler_;
482 scoped_ptr<NetworkConfigurationHandler> network_configuration_handler_;
483 scoped_ptr<TestObserver> test_observer_;
484 base::MessageLoopForUI message_loop_;
485 std::string success_callback_name_;
486 std::string get_properties_path_;
487 scoped_ptr<DictionaryValue> get_properties_;
488 std::string create_service_path_;
491 TEST_F(NetworkConfigurationHandlerStubTest, StubSetAndClearProperties) {
492 // TODO(stevenjb): Remove dependency on default Stub service.
493 const std::string service_path("wifi1");
494 const std::string test_identity("test_identity");
495 const std::string test_passphrase("test_passphrase");
498 base::DictionaryValue properties_to_set;
499 properties_to_set.SetStringWithoutPathExpansion(
500 shill::kIdentityProperty, test_identity);
501 properties_to_set.SetStringWithoutPathExpansion(
502 shill::kPassphraseProperty, test_passphrase);
503 network_configuration_handler_->SetProperties(
507 &NetworkConfigurationHandlerStubTest::SuccessCallback,
508 base::Unretained(this), "SetProperties"),
509 base::Bind(&ErrorCallback, false, service_path));
510 message_loop_.RunUntilIdle();
512 EXPECT_EQ("SetProperties", success_callback_name_);
513 std::string identity, passphrase;
514 EXPECT_TRUE(GetServiceStringProperty(
515 service_path, shill::kIdentityProperty, &identity));
516 EXPECT_TRUE(GetServiceStringProperty(
517 service_path, shill::kPassphraseProperty, &passphrase));
518 EXPECT_EQ(test_identity, identity);
519 EXPECT_EQ(test_passphrase, passphrase);
520 EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(service_path));
523 std::vector<std::string> properties_to_clear;
524 properties_to_clear.push_back(shill::kIdentityProperty);
525 properties_to_clear.push_back(shill::kPassphraseProperty);
526 network_configuration_handler_->ClearProperties(
530 &NetworkConfigurationHandlerStubTest::SuccessCallback,
531 base::Unretained(this), "ClearProperties"),
532 base::Bind(&ErrorCallback, false, service_path));
533 message_loop_.RunUntilIdle();
535 EXPECT_EQ("ClearProperties", success_callback_name_);
536 EXPECT_FALSE(GetServiceStringProperty(
537 service_path, shill::kIdentityProperty, &identity));
538 EXPECT_FALSE(GetServiceStringProperty(
539 service_path, shill::kIdentityProperty, &passphrase));
540 EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(service_path));
543 TEST_F(NetworkConfigurationHandlerStubTest, StubGetNameFromWifiHex) {
544 // TODO(stevenjb): Remove dependency on default Stub service.
545 const std::string service_path("wifi1");
546 std::string wifi_hex = "5468697320697320484558205353494421";
547 std::string expected_name = "This is HEX SSID!";
550 base::DictionaryValue properties_to_set;
551 properties_to_set.SetStringWithoutPathExpansion(
552 shill::kWifiHexSsid, wifi_hex);
553 network_configuration_handler_->SetProperties(
556 base::Bind(&base::DoNothing),
557 base::Bind(&ErrorCallback, false, service_path));
558 message_loop_.RunUntilIdle();
559 std::string wifi_hex_result;
560 EXPECT_TRUE(GetServiceStringProperty(
561 service_path, shill::kWifiHexSsid, &wifi_hex_result));
562 EXPECT_EQ(wifi_hex, wifi_hex_result);
565 network_configuration_handler_->GetProperties(
567 base::Bind(&NetworkConfigurationHandlerStubTest::GetPropertiesCallback,
568 base::Unretained(this)),
569 base::Bind(&ErrorCallback, false, service_path));
570 message_loop_.RunUntilIdle();
572 EXPECT_EQ(service_path, get_properties_path_);
573 std::string name_result;
574 EXPECT_TRUE(GetReceivedStringProperty(
575 service_path, shill::kNameProperty, &name_result));
576 EXPECT_EQ(expected_name, name_result);
579 TEST_F(NetworkConfigurationHandlerStubTest, StubCreateConfiguration) {
580 const std::string service_path("test_wifi");
581 base::DictionaryValue properties;
582 shill_property_util::SetSSID(service_path, &properties);
583 properties.SetStringWithoutPathExpansion(shill::kNameProperty, service_path);
584 properties.SetStringWithoutPathExpansion(shill::kGuidProperty, service_path);
585 properties.SetStringWithoutPathExpansion(
586 shill::kTypeProperty, shill::kTypeWifi);
587 properties.SetStringWithoutPathExpansion(
588 shill::kStateProperty, shill::kStateIdle);
589 properties.SetStringWithoutPathExpansion(
590 shill::kProfileProperty, shill_stub_helper::kSharedProfilePath);
592 network_configuration_handler_->CreateConfiguration(
595 &NetworkConfigurationHandlerStubTest::CreateConfigurationCallback,
596 base::Unretained(this)),
597 base::Bind(&ErrorCallback, false, service_path));
598 message_loop_.RunUntilIdle();
600 EXPECT_FALSE(create_service_path_.empty());
603 EXPECT_TRUE(GetServiceStringProperty(
604 create_service_path_, shill::kGuidProperty, &guid));
605 EXPECT_EQ(service_path, guid);
607 std::string actual_profile;
608 EXPECT_TRUE(GetServiceStringProperty(
609 create_service_path_, shill::kProfileProperty, &actual_profile));
610 EXPECT_EQ(shill_stub_helper::kSharedProfilePath, actual_profile);
613 } // namespace chromeos