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 "base/bind.h" 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/network/network_configuration_handler.h" 16 #include "chromeos/network/network_profile_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" 24 25 using ::testing::_; 26 using ::testing::AnyNumber; 27 using ::testing::Invoke; 28 using ::testing::Pointee; 29 using ::testing::Return; 30 using ::testing::SaveArg; 31 using ::testing::StrEq; 32 33 // Matcher to match base::Value. 34 MATCHER_P(IsEqualTo, value, "") { return arg.Equals(value); } 35 36 namespace chromeos { 37 38 namespace { 39 40 static std::string PrettyJson(const base::DictionaryValue& value) { 41 std::string pretty; 42 base::JSONWriter::WriteWithOptions(&value, 43 base::JSONWriter::OPTIONS_PRETTY_PRINT, 44 &pretty); 45 return pretty; 46 } 47 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); 56 } 57 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); 65 } 66 67 void StringResultCallback(const std::string& expected_result, 68 const std::string& result) { 69 EXPECT_EQ(expected_result, result); 70 } 71 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 << ")"; 76 } 77 78 class TestCallback { 79 public: 80 TestCallback() : run_count_(0) {} 81 void Run() { 82 ++run_count_; 83 } 84 int run_count() const { return run_count_; } 85 86 private: 87 int run_count_; 88 }; 89 90 } // namespace 91 92 class NetworkConfigurationHandlerTest : public testing::Test { 93 public: 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() {} 100 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()); 112 113 EXPECT_CALL(*mock_service_client_, GetProperties(_, _)) 114 .Times(AnyNumber()); 115 EXPECT_CALL(*mock_manager_client_, GetProperties(_)) 116 .Times(AnyNumber()); 117 EXPECT_CALL(*mock_manager_client_, AddPropertyChangedObserver(_)) 118 .Times(AnyNumber()); 119 EXPECT_CALL(*mock_manager_client_, RemovePropertyChangedObserver(_)) 120 .Times(AnyNumber()); 121 122 DBusThreadManager::InitializeForTesting(dbus_thread_manager); 123 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(); 128 } 129 130 virtual void TearDown() OVERRIDE { 131 network_configuration_handler_.reset(); 132 network_state_handler_.reset(); 133 DBusThreadManager::Shutdown(); 134 } 135 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_); 141 } 142 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) { 148 callback.Run(); 149 } 150 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); 160 } 161 162 // Handles responses for ClearProperties method calls, and simulates an error 163 // result. 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); 172 } 173 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")); 180 } 181 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); 189 } 190 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); 197 } 198 199 bool PendingProfileEntryDeleterForTest(const std::string& service_path) { 200 return network_configuration_handler_-> 201 PendingProfileEntryDeleterForTest(service_path); 202 } 203 204 protected: 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_; 212 }; 213 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)); 221 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), 229 key, 230 *networkNameValue, 231 base::Bind(&base::DoNothing), 232 base::Bind(&DBusErrorCallback)); 233 message_loop_.RunUntilIdle(); 234 235 ShillServiceClient::DictionaryValueCallback get_properties_callback; 236 EXPECT_CALL(*mock_service_client_, 237 GetProperties(_, _)).WillOnce( 238 Invoke(this, 239 &NetworkConfigurationHandlerTest::OnGetProperties)); 240 network_configuration_handler_->GetProperties( 241 service_path, 242 base::Bind(&DictionaryValueCallback, 243 service_path, 244 expected_json), 245 base::Bind(&ErrorCallback, false, service_path)); 246 message_loop_.RunUntilIdle(); 247 } 248 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)); 255 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( 261 Invoke(this, 262 &NetworkConfigurationHandlerTest::OnSetProperties)); 263 network_configuration_handler_->SetProperties( 264 service_path, 265 value, 266 base::Bind(&base::DoNothing), 267 base::Bind(&ErrorCallback, false, service_path)); 268 message_loop_.RunUntilIdle(); 269 } 270 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)); 277 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( 284 Invoke(this, 285 &NetworkConfigurationHandlerTest::OnSetProperties)); 286 network_configuration_handler_->SetProperties( 287 service_path, 288 value, 289 base::Bind(&base::DoNothing), 290 base::Bind(&ErrorCallback, false, service_path)); 291 message_loop_.RunUntilIdle(); 292 293 // Now clear it. 294 std::vector<std::string> values_to_clear; 295 values_to_clear.push_back(key); 296 EXPECT_CALL(*mock_service_client_, 297 ClearProperties(_, _, _, _)).WillOnce( 298 Invoke(this, 299 &NetworkConfigurationHandlerTest::OnClearProperties)); 300 network_configuration_handler_->ClearProperties( 301 service_path, 302 values_to_clear, 303 base::Bind(&base::DoNothing), 304 base::Bind(&ErrorCallback, false, service_path)); 305 message_loop_.RunUntilIdle(); 306 } 307 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)); 314 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( 321 Invoke(this, 322 &NetworkConfigurationHandlerTest::OnSetProperties)); 323 network_configuration_handler_->SetProperties( 324 service_path, 325 value, 326 base::Bind(&base::DoNothing), 327 base::Bind(&ErrorCallback, false, service_path)); 328 message_loop_.RunUntilIdle(); 329 330 // Now clear it. 331 std::vector<std::string> values_to_clear; 332 values_to_clear.push_back(key); 333 EXPECT_CALL( 334 *mock_service_client_, 335 ClearProperties(_, _, _, _)).WillOnce( 336 Invoke(this, 337 &NetworkConfigurationHandlerTest::OnClearPropertiesError)); 338 network_configuration_handler_->ClearProperties( 339 service_path, 340 values_to_clear, 341 base::Bind(&base::DoNothing), 342 base::Bind(&ErrorCallback, true, service_path)); 343 message_loop_.RunUntilIdle(); 344 } 345 346 TEST_F(NetworkConfigurationHandlerTest, CreateConfiguration) { 347 std::string networkName = "MyNetwork"; 348 std::string key = "SSID"; 349 std::string type = "wifi"; 350 std::string profile = "profile path"; 351 base::DictionaryValue value; 352 shill_property_util::SetSSID(networkName, &value); 353 value.SetWithoutPathExpansion(shill::kTypeProperty, 354 base::Value::CreateStringValue(type)); 355 value.SetWithoutPathExpansion(shill::kProfileProperty, 356 base::Value::CreateStringValue(profile)); 357 358 EXPECT_CALL(*mock_manager_client_, 359 ConfigureServiceForProfile(dbus::ObjectPath(profile), _, _, _)) 360 .WillOnce( 361 Invoke(this, &NetworkConfigurationHandlerTest::OnConfigureService)); 362 network_configuration_handler_->CreateConfiguration( 363 value, 364 base::Bind(&StringResultCallback, std::string("/service/2")), 365 base::Bind(&ErrorCallback, false, std::string())); 366 message_loop_.RunUntilIdle(); 367 } 368 369 TEST_F(NetworkConfigurationHandlerTest, RemoveConfiguration) { 370 std::string service_path = "/service/1"; 371 372 TestCallback test_callback; 373 EXPECT_CALL( 374 *mock_service_client_, 375 GetLoadableProfileEntries(_, _)).WillOnce(Invoke( 376 this, 377 &NetworkConfigurationHandlerTest::OnGetLoadableProfileEntries)); 378 EXPECT_CALL( 379 *mock_profile_client_, 380 DeleteEntry(_, _, _, _)).WillRepeatedly(Invoke( 381 this, 382 &NetworkConfigurationHandlerTest::OnDeleteEntry)); 383 384 network_configuration_handler_->RemoveConfiguration( 385 service_path, 386 base::Bind(&TestCallback::Run, base::Unretained(&test_callback)), 387 base::Bind(&ErrorCallback, false, service_path)); 388 message_loop_.RunUntilIdle(); 389 EXPECT_EQ(1, test_callback.run_count()); 390 EXPECT_FALSE(PendingProfileEntryDeleterForTest(service_path)); 391 } 392 393 //////////////////////////////////////////////////////////////////////////////// 394 // Stub based tests 395 396 namespace { 397 398 class TestObserver : public chromeos::NetworkStateHandlerObserver { 399 public: 400 TestObserver() : network_list_changed_count_(0) {} 401 virtual ~TestObserver() {} 402 403 virtual void NetworkListChanged() OVERRIDE { 404 ++network_list_changed_count_; 405 } 406 407 virtual void NetworkPropertiesUpdated(const NetworkState* network) OVERRIDE { 408 property_updates_[network->path()]++; 409 } 410 411 size_t network_list_changed_count() { return network_list_changed_count_; } 412 413 int PropertyUpdatesForService(const std::string& service_path) { 414 return property_updates_[service_path]; 415 } 416 417 void ClearPropertyUpdates() { 418 property_updates_.clear(); 419 } 420 421 private: 422 size_t network_list_changed_count_; 423 std::map<std::string, int> property_updates_; 424 425 DISALLOW_COPY_AND_ASSIGN(TestObserver); 426 }; 427 428 } // namespace 429 430 class NetworkConfigurationHandlerStubTest : public testing::Test { 431 public: 432 NetworkConfigurationHandlerStubTest() { 433 } 434 435 virtual ~NetworkConfigurationHandlerStubTest() { 436 } 437 438 virtual void SetUp() OVERRIDE { 439 DBusThreadManager::InitializeWithStub(); 440 441 network_state_handler_.reset(NetworkStateHandler::InitializeForTest()); 442 test_observer_.reset(new TestObserver()); 443 network_state_handler_->AddObserver(test_observer_.get(), FROM_HERE); 444 445 network_configuration_handler_.reset(new NetworkConfigurationHandler()); 446 network_configuration_handler_->Init(network_state_handler_.get()); 447 448 message_loop_.RunUntilIdle(); 449 test_observer_->ClearPropertyUpdates(); 450 } 451 452 virtual void TearDown() OVERRIDE { 453 network_configuration_handler_.reset(); 454 network_state_handler_->RemoveObserver(test_observer_.get(), FROM_HERE); 455 network_state_handler_.reset(); 456 DBusThreadManager::Shutdown(); 457 } 458 459 void SuccessCallback(const std::string& callback_name) { 460 success_callback_name_ = callback_name; 461 } 462 463 void GetPropertiesCallback(const std::string& service_path, 464 const base::DictionaryValue& dictionary) { 465 get_properties_path_ = service_path; 466 get_properties_.reset(dictionary.DeepCopy()); 467 } 468 469 void CreateConfigurationCallback(const std::string& service_path) { 470 create_service_path_ = service_path; 471 } 472 473 protected: 474 bool GetServiceStringProperty(const std::string& service_path, 475 const std::string& key, 476 std::string* result) { 477 ShillServiceClient::TestInterface* service_test = 478 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); 479 const base::DictionaryValue* properties = 480 service_test->GetServiceProperties(service_path); 481 if (properties && properties->GetStringWithoutPathExpansion(key, result)) 482 return true; 483 return false; 484 } 485 486 bool GetReceivedStringProperty(const std::string& service_path, 487 const std::string& key, 488 std::string* result) { 489 if (get_properties_path_ != service_path) 490 return false; 491 if (get_properties_ && 492 get_properties_->GetStringWithoutPathExpansion(key, result)) 493 return true; 494 return false; 495 } 496 497 scoped_ptr<NetworkStateHandler> network_state_handler_; 498 scoped_ptr<NetworkConfigurationHandler> network_configuration_handler_; 499 scoped_ptr<TestObserver> test_observer_; 500 base::MessageLoopForUI message_loop_; 501 std::string success_callback_name_; 502 std::string get_properties_path_; 503 scoped_ptr<base::DictionaryValue> get_properties_; 504 std::string create_service_path_; 505 }; 506 507 TEST_F(NetworkConfigurationHandlerStubTest, StubSetAndClearProperties) { 508 // TODO(stevenjb): Remove dependency on default Stub service. 509 const std::string service_path("/service/wifi1"); 510 const std::string test_identity("test_identity"); 511 const std::string test_passphrase("test_passphrase"); 512 513 // Set Properties 514 base::DictionaryValue properties_to_set; 515 properties_to_set.SetStringWithoutPathExpansion( 516 shill::kIdentityProperty, test_identity); 517 properties_to_set.SetStringWithoutPathExpansion( 518 shill::kPassphraseProperty, test_passphrase); 519 network_configuration_handler_->SetProperties( 520 service_path, 521 properties_to_set, 522 base::Bind( 523 &NetworkConfigurationHandlerStubTest::SuccessCallback, 524 base::Unretained(this), "SetProperties"), 525 base::Bind(&ErrorCallback, false, service_path)); 526 message_loop_.RunUntilIdle(); 527 528 EXPECT_EQ("SetProperties", success_callback_name_); 529 std::string identity, passphrase; 530 EXPECT_TRUE(GetServiceStringProperty( 531 service_path, shill::kIdentityProperty, &identity)); 532 EXPECT_TRUE(GetServiceStringProperty( 533 service_path, shill::kPassphraseProperty, &passphrase)); 534 EXPECT_EQ(test_identity, identity); 535 EXPECT_EQ(test_passphrase, passphrase); 536 EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(service_path)); 537 538 // Clear Properties 539 std::vector<std::string> properties_to_clear; 540 properties_to_clear.push_back(shill::kIdentityProperty); 541 properties_to_clear.push_back(shill::kPassphraseProperty); 542 network_configuration_handler_->ClearProperties( 543 service_path, 544 properties_to_clear, 545 base::Bind( 546 &NetworkConfigurationHandlerStubTest::SuccessCallback, 547 base::Unretained(this), "ClearProperties"), 548 base::Bind(&ErrorCallback, false, service_path)); 549 message_loop_.RunUntilIdle(); 550 551 EXPECT_EQ("ClearProperties", success_callback_name_); 552 EXPECT_FALSE(GetServiceStringProperty( 553 service_path, shill::kIdentityProperty, &identity)); 554 EXPECT_FALSE(GetServiceStringProperty( 555 service_path, shill::kIdentityProperty, &passphrase)); 556 EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(service_path)); 557 } 558 559 TEST_F(NetworkConfigurationHandlerStubTest, StubGetNameFromWifiHex) { 560 // TODO(stevenjb): Remove dependency on default Stub service. 561 const std::string service_path("/service/wifi1"); 562 std::string wifi_hex = "5468697320697320484558205353494421"; 563 std::string expected_name = "This is HEX SSID!"; 564 565 // Set Properties 566 base::DictionaryValue properties_to_set; 567 properties_to_set.SetStringWithoutPathExpansion( 568 shill::kWifiHexSsid, wifi_hex); 569 network_configuration_handler_->SetProperties( 570 service_path, 571 properties_to_set, 572 base::Bind(&base::DoNothing), 573 base::Bind(&ErrorCallback, false, service_path)); 574 message_loop_.RunUntilIdle(); 575 std::string wifi_hex_result; 576 EXPECT_TRUE(GetServiceStringProperty( 577 service_path, shill::kWifiHexSsid, &wifi_hex_result)); 578 EXPECT_EQ(wifi_hex, wifi_hex_result); 579 580 // Get Properties 581 network_configuration_handler_->GetProperties( 582 service_path, 583 base::Bind(&NetworkConfigurationHandlerStubTest::GetPropertiesCallback, 584 base::Unretained(this)), 585 base::Bind(&ErrorCallback, false, service_path)); 586 message_loop_.RunUntilIdle(); 587 588 EXPECT_EQ(service_path, get_properties_path_); 589 std::string name_result; 590 EXPECT_TRUE(GetReceivedStringProperty( 591 service_path, shill::kNameProperty, &name_result)); 592 EXPECT_EQ(expected_name, name_result); 593 } 594 595 TEST_F(NetworkConfigurationHandlerStubTest, StubCreateConfiguration) { 596 const std::string service_path("/service/test_wifi"); 597 base::DictionaryValue properties; 598 shill_property_util::SetSSID(service_path, &properties); 599 properties.SetStringWithoutPathExpansion(shill::kNameProperty, service_path); 600 properties.SetStringWithoutPathExpansion(shill::kGuidProperty, service_path); 601 properties.SetStringWithoutPathExpansion( 602 shill::kTypeProperty, shill::kTypeWifi); 603 properties.SetStringWithoutPathExpansion( 604 shill::kStateProperty, shill::kStateIdle); 605 properties.SetStringWithoutPathExpansion( 606 shill::kProfileProperty, NetworkProfileHandler::GetSharedProfilePath()); 607 608 network_configuration_handler_->CreateConfiguration( 609 properties, 610 base::Bind( 611 &NetworkConfigurationHandlerStubTest::CreateConfigurationCallback, 612 base::Unretained(this)), 613 base::Bind(&ErrorCallback, false, service_path)); 614 message_loop_.RunUntilIdle(); 615 616 EXPECT_FALSE(create_service_path_.empty()); 617 618 std::string guid; 619 EXPECT_TRUE(GetServiceStringProperty( 620 create_service_path_, shill::kGuidProperty, &guid)); 621 EXPECT_EQ(service_path, guid); 622 623 std::string actual_profile; 624 EXPECT_TRUE(GetServiceStringProperty( 625 create_service_path_, shill::kProfileProperty, &actual_profile)); 626 EXPECT_EQ(NetworkProfileHandler::GetSharedProfilePath(), actual_profile); 627 } 628 629 } // namespace chromeos 630