Home | History | Annotate | Download | only in network
      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/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_profile_client_stub.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 "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"
     23 
     24 using ::testing::_;
     25 using ::testing::Invoke;
     26 using ::testing::Pointee;
     27 using ::testing::Return;
     28 using ::testing::SaveArg;
     29 using ::testing::StrEq;
     30 
     31 // Matcher to match base::Value.
     32 MATCHER_P(IsEqualTo, value, "") { return arg.Equals(value); }
     33 
     34 namespace chromeos {
     35 
     36 namespace {
     37 
     38 static std::string PrettyJson(const base::DictionaryValue& value) {
     39   std::string pretty;
     40   base::JSONWriter::WriteWithOptions(&value,
     41                                      base::JSONWriter::OPTIONS_PRETTY_PRINT,
     42                                      &pretty);
     43   return pretty;
     44 }
     45 
     46 void DictionaryValueCallback(
     47     const std::string& expected_id,
     48     const std::string& expected_json,
     49     const std::string& service_path,
     50     const base::DictionaryValue& dictionary) {
     51   std::string dict_str = PrettyJson(dictionary);
     52   EXPECT_EQ(expected_json, dict_str);
     53   EXPECT_EQ(expected_id, service_path);
     54 }
     55 
     56 void ErrorCallback(bool error_expected,
     57                    const std::string& expected_id,
     58                    const std::string& error_name,
     59                    scoped_ptr<base::DictionaryValue> error_data) {
     60   EXPECT_TRUE(error_expected) << "Unexpected error: " << error_name
     61       << " with associated data: \n"
     62       << PrettyJson(*error_data);
     63 }
     64 
     65 void StringResultCallback(const std::string& expected_result,
     66                           const std::string& result) {
     67   EXPECT_EQ(expected_result, result);
     68 }
     69 
     70 void DBusErrorCallback(const std::string& error_name,
     71                        const std::string& error_message) {
     72   EXPECT_TRUE(false) << "DBus Error: " << error_name << "("
     73       << error_message << ")";
     74 }
     75 
     76 class TestCallback {
     77  public:
     78   TestCallback() : run_count_(0) {}
     79   void Run() {
     80     ++run_count_;
     81   }
     82   int run_count() const { return run_count_; }
     83 
     84  private:
     85   int run_count_;
     86 };
     87 
     88 }  // namespace
     89 
     90 class NetworkConfigurationHandlerTest : public testing::Test {
     91  public:
     92   NetworkConfigurationHandlerTest()
     93       : mock_manager_client_(NULL),
     94         mock_profile_client_(NULL),
     95         mock_service_client_(NULL),
     96         dictionary_value_result_(NULL) {}
     97   virtual ~NetworkConfigurationHandlerTest() {}
     98 
     99   virtual void SetUp() OVERRIDE {
    100     MockDBusThreadManager* mock_dbus_thread_manager = new MockDBusThreadManager;
    101     EXPECT_CALL(*mock_dbus_thread_manager, GetSystemBus())
    102     .WillRepeatedly(Return(reinterpret_cast<dbus::Bus*>(NULL)));
    103     DBusThreadManager::InitializeForTesting(mock_dbus_thread_manager);
    104     mock_manager_client_ =
    105         mock_dbus_thread_manager->mock_shill_manager_client();
    106     mock_profile_client_ =
    107         mock_dbus_thread_manager->mock_shill_profile_client();
    108     mock_service_client_ =
    109         mock_dbus_thread_manager->mock_shill_service_client();
    110 
    111     network_state_handler_.reset(NetworkStateHandler::InitializeForTest());
    112     network_configuration_handler_.reset(new NetworkConfigurationHandler());
    113     network_configuration_handler_->Init(network_state_handler_.get());
    114     message_loop_.RunUntilIdle();
    115   }
    116 
    117   virtual void TearDown() OVERRIDE {
    118     network_configuration_handler_.reset();
    119     network_state_handler_.reset();
    120     DBusThreadManager::Shutdown();
    121   }
    122 
    123   // Handles responses for GetProperties method calls.
    124   void OnGetProperties(
    125       const dbus::ObjectPath& path,
    126       const ShillClientHelper::DictionaryValueCallback& callback) {
    127     callback.Run(DBUS_METHOD_CALL_SUCCESS, *dictionary_value_result_);
    128   }
    129 
    130   // Handles responses for SetProperties method calls.
    131   void OnSetProperties(const dbus::ObjectPath& service_path,
    132                        const base::DictionaryValue& properties,
    133                        const base::Closure& callback,
    134                        const ShillClientHelper::ErrorCallback& error_callback) {
    135     callback.Run();
    136   }
    137 
    138   // Handles responses for ClearProperties method calls.
    139   void OnClearProperties(
    140       const dbus::ObjectPath& service_path,
    141       const std::vector<std::string>& names,
    142       const ShillClientHelper::ListValueCallback& callback,
    143       const ShillClientHelper::ErrorCallback& error_callback) {
    144     base::ListValue result;
    145     result.AppendBoolean(true);
    146     callback.Run(result);
    147   }
    148 
    149   // Handles responses for ClearProperties method calls, and simulates an error
    150   // result.
    151   void OnClearPropertiesError(
    152       const dbus::ObjectPath& service_path,
    153       const std::vector<std::string>& names,
    154       const ShillClientHelper::ListValueCallback& callback,
    155       const ShillClientHelper::ErrorCallback& error_callback) {
    156     base::ListValue result;
    157     result.AppendBoolean(false);
    158     callback.Run(result);
    159   }
    160 
    161   void OnConfigureService(
    162       const dbus::ObjectPath& profile_path,
    163       const base::DictionaryValue& properties,
    164       const ObjectPathCallback& callback,
    165       const ShillClientHelper::ErrorCallback& error_callback) {
    166     callback.Run(dbus::ObjectPath("/service/2"));
    167   }
    168 
    169   void OnGetLoadableProfileEntries(
    170       const dbus::ObjectPath& service_path,
    171       const ShillClientHelper::DictionaryValueCallback& callback) {
    172     base::DictionaryValue entries;
    173     entries.SetString("profile1", "entry1");
    174     entries.SetString("profile2", "entry2");
    175     callback.Run(DBUS_METHOD_CALL_SUCCESS, entries);
    176   }
    177 
    178   void OnDeleteEntry(const dbus::ObjectPath& profile_path,
    179                      const std::string& entry_path,
    180                      const base::Closure& callback,
    181                      const ShillClientHelper::ErrorCallback& error_callback) {
    182     // Don't run the callback immediately to emulate actual behavior.
    183     message_loop_.PostTask(FROM_HERE, callback);
    184   }
    185 
    186   bool PendingProfileEntryDeleterForTest(const std::string& service_path) {
    187     return network_configuration_handler_->
    188         PendingProfileEntryDeleterForTest(service_path);
    189   }
    190 
    191  protected:
    192   MockShillManagerClient* mock_manager_client_;
    193   MockShillProfileClient* mock_profile_client_;
    194   MockShillServiceClient* mock_service_client_;
    195   scoped_ptr<NetworkStateHandler> network_state_handler_;
    196   scoped_ptr<NetworkConfigurationHandler> network_configuration_handler_;
    197   base::MessageLoopForUI message_loop_;
    198   base::DictionaryValue* dictionary_value_result_;
    199 };
    200 
    201 TEST_F(NetworkConfigurationHandlerTest, GetProperties) {
    202   std::string service_path = "/service/1";
    203   std::string expected_json = "{\n   \"SSID\": \"MyNetwork\"\n}\n";
    204   std::string networkName = "MyNetwork";
    205   std::string key = "SSID";
    206   scoped_ptr<base::StringValue> networkNameValue(
    207       base::Value::CreateStringValue(networkName));
    208 
    209   base::DictionaryValue value;
    210   value.Set(key, base::Value::CreateStringValue(networkName));
    211   dictionary_value_result_ = &value;
    212   EXPECT_CALL(*mock_service_client_,
    213               SetProperty(dbus::ObjectPath(service_path), key,
    214                           IsEqualTo(networkNameValue.get()), _, _)).Times(1);
    215   DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
    216       dbus::ObjectPath(service_path), key, *networkNameValue,
    217       base::Bind(&base::DoNothing),
    218       base::Bind(&DBusErrorCallback));
    219   message_loop_.RunUntilIdle();
    220 
    221   ShillServiceClient::DictionaryValueCallback get_properties_callback;
    222   EXPECT_CALL(*mock_service_client_,
    223               GetProperties(_, _)).WillOnce(
    224                   Invoke(this,
    225                          &NetworkConfigurationHandlerTest::OnGetProperties));
    226   network_configuration_handler_->GetProperties(
    227       service_path,
    228       base::Bind(&DictionaryValueCallback,
    229                  service_path,
    230                  expected_json),
    231                  base::Bind(&ErrorCallback, false, service_path));
    232   message_loop_.RunUntilIdle();
    233 }
    234 
    235 TEST_F(NetworkConfigurationHandlerTest, SetProperties) {
    236   std::string service_path = "/service/1";
    237   std::string networkName = "MyNetwork";
    238   std::string key = "SSID";
    239   scoped_ptr<base::StringValue> networkNameValue(
    240       base::Value::CreateStringValue(networkName));
    241 
    242   base::DictionaryValue value;
    243   value.Set(key, base::Value::CreateStringValue(networkName));
    244   dictionary_value_result_ = &value;
    245   EXPECT_CALL(*mock_service_client_,
    246               SetProperties(_, _, _, _)).WillOnce(
    247                   Invoke(this,
    248                          &NetworkConfigurationHandlerTest::OnSetProperties));
    249   network_configuration_handler_->SetProperties(
    250       service_path,
    251       value,
    252       base::Bind(&base::DoNothing),
    253       base::Bind(&ErrorCallback, false, service_path));
    254   message_loop_.RunUntilIdle();
    255 }
    256 
    257 TEST_F(NetworkConfigurationHandlerTest, ClearProperties) {
    258   std::string service_path = "/service/1";
    259   std::string networkName = "MyNetwork";
    260   std::string key = "SSID";
    261   scoped_ptr<base::StringValue> networkNameValue(
    262       base::Value::CreateStringValue(networkName));
    263 
    264   // First set up a value to clear.
    265   base::DictionaryValue value;
    266   value.Set(key, base::Value::CreateStringValue(networkName));
    267   dictionary_value_result_ = &value;
    268   EXPECT_CALL(*mock_service_client_,
    269               SetProperties(_, _, _, _)).WillOnce(
    270                   Invoke(this,
    271                          &NetworkConfigurationHandlerTest::OnSetProperties));
    272   network_configuration_handler_->SetProperties(
    273       service_path,
    274       value,
    275       base::Bind(&base::DoNothing),
    276       base::Bind(&ErrorCallback, false, service_path));
    277   message_loop_.RunUntilIdle();
    278 
    279   // Now clear it.
    280   std::vector<std::string> values_to_clear;
    281   values_to_clear.push_back(key);
    282   EXPECT_CALL(*mock_service_client_,
    283               ClearProperties(_, _, _, _)).WillOnce(
    284                   Invoke(this,
    285                          &NetworkConfigurationHandlerTest::OnClearProperties));
    286   network_configuration_handler_->ClearProperties(
    287       service_path,
    288       values_to_clear,
    289       base::Bind(&base::DoNothing),
    290       base::Bind(&ErrorCallback, false, service_path));
    291   message_loop_.RunUntilIdle();
    292 }
    293 
    294 TEST_F(NetworkConfigurationHandlerTest, ClearPropertiesError) {
    295   std::string service_path = "/service/1";
    296   std::string networkName = "MyNetwork";
    297   std::string key = "SSID";
    298   scoped_ptr<base::StringValue> networkNameValue(
    299       base::Value::CreateStringValue(networkName));
    300 
    301   // First set up a value to clear.
    302   base::DictionaryValue value;
    303   value.Set(key, base::Value::CreateStringValue(networkName));
    304   dictionary_value_result_ = &value;
    305   EXPECT_CALL(*mock_service_client_,
    306               SetProperties(_, _, _, _)).WillOnce(
    307                   Invoke(this,
    308                          &NetworkConfigurationHandlerTest::OnSetProperties));
    309   network_configuration_handler_->SetProperties(
    310       service_path,
    311       value,
    312       base::Bind(&base::DoNothing),
    313       base::Bind(&ErrorCallback, false, service_path));
    314   message_loop_.RunUntilIdle();
    315 
    316   // Now clear it.
    317   std::vector<std::string> values_to_clear;
    318   values_to_clear.push_back(key);
    319   EXPECT_CALL(
    320       *mock_service_client_,
    321       ClearProperties(_, _, _, _)).WillOnce(
    322           Invoke(this,
    323                  &NetworkConfigurationHandlerTest::OnClearPropertiesError));
    324   network_configuration_handler_->ClearProperties(
    325       service_path,
    326       values_to_clear,
    327       base::Bind(&base::DoNothing),
    328       base::Bind(&ErrorCallback, true, service_path));
    329   message_loop_.RunUntilIdle();
    330 }
    331 
    332 TEST_F(NetworkConfigurationHandlerTest, CreateConfiguration) {
    333   std::string networkName = "MyNetwork";
    334   std::string key = "SSID";
    335   std::string profile = "profile path";
    336   scoped_ptr<base::StringValue> networkNameValue(
    337       base::Value::CreateStringValue(networkName));
    338   base::DictionaryValue value;
    339   value.SetWithoutPathExpansion(flimflam::kSSIDProperty,
    340                                 base::Value::CreateStringValue(networkName));
    341   value.SetWithoutPathExpansion(flimflam::kProfileProperty,
    342                                 base::Value::CreateStringValue(profile));
    343 
    344   EXPECT_CALL(*mock_manager_client_,
    345               ConfigureServiceForProfile(dbus::ObjectPath(profile), _, _, _))
    346       .WillOnce(
    347            Invoke(this, &NetworkConfigurationHandlerTest::OnConfigureService));
    348   network_configuration_handler_->CreateConfiguration(
    349       value,
    350       base::Bind(&StringResultCallback, std::string("/service/2")),
    351       base::Bind(&ErrorCallback, false, std::string("")));
    352   message_loop_.RunUntilIdle();
    353 }
    354 
    355 TEST_F(NetworkConfigurationHandlerTest, RemoveConfiguration) {
    356   std::string service_path = "/service/1";
    357 
    358   TestCallback test_callback;
    359   EXPECT_CALL(
    360       *mock_service_client_,
    361       GetLoadableProfileEntries(_, _)).WillOnce(Invoke(
    362           this,
    363           &NetworkConfigurationHandlerTest::OnGetLoadableProfileEntries));
    364   EXPECT_CALL(
    365       *mock_profile_client_,
    366       DeleteEntry(_, _, _, _)).WillRepeatedly(Invoke(
    367           this,
    368           &NetworkConfigurationHandlerTest::OnDeleteEntry));
    369 
    370   network_configuration_handler_->RemoveConfiguration(
    371       service_path,
    372       base::Bind(&TestCallback::Run, base::Unretained(&test_callback)),
    373       base::Bind(&ErrorCallback, false, service_path));
    374   message_loop_.RunUntilIdle();
    375   EXPECT_EQ(1, test_callback.run_count());
    376   EXPECT_FALSE(PendingProfileEntryDeleterForTest(service_path));
    377 }
    378 
    379 ////////////////////////////////////////////////////////////////////////////////
    380 // Stub based tests
    381 
    382 namespace {
    383 
    384 class TestObserver : public chromeos::NetworkStateHandlerObserver {
    385  public:
    386   TestObserver() : network_list_changed_count_(0) {}
    387   virtual ~TestObserver() {}
    388 
    389   virtual void NetworkListChanged() OVERRIDE {
    390     ++network_list_changed_count_;
    391   }
    392 
    393   virtual void NetworkPropertiesUpdated(const NetworkState* network) OVERRIDE {
    394     property_updates_[network->path()]++;
    395   }
    396 
    397   size_t network_list_changed_count() { return network_list_changed_count_; }
    398 
    399   int PropertyUpdatesForService(const std::string& service_path) {
    400     return property_updates_[service_path];
    401   }
    402 
    403   void ClearPropertyUpdates() {
    404     property_updates_.clear();
    405   }
    406 
    407  private:
    408   size_t network_list_changed_count_;
    409   std::map<std::string, int> property_updates_;
    410 
    411   DISALLOW_COPY_AND_ASSIGN(TestObserver);
    412 };
    413 
    414 }  // namespace
    415 
    416 class NetworkConfigurationHandlerStubTest : public testing::Test {
    417  public:
    418   NetworkConfigurationHandlerStubTest()  {
    419   }
    420 
    421   virtual ~NetworkConfigurationHandlerStubTest() {
    422   }
    423 
    424   virtual void SetUp() OVERRIDE {
    425     DBusThreadManager::InitializeWithStub();
    426 
    427     network_state_handler_.reset(NetworkStateHandler::InitializeForTest());
    428     test_observer_.reset(new TestObserver());
    429     network_state_handler_->AddObserver(test_observer_.get(), FROM_HERE);
    430 
    431     network_configuration_handler_.reset(new NetworkConfigurationHandler());
    432     network_configuration_handler_->Init(network_state_handler_.get());
    433 
    434     message_loop_.RunUntilIdle();
    435     test_observer_->ClearPropertyUpdates();
    436   }
    437 
    438   virtual void TearDown() OVERRIDE {
    439     network_configuration_handler_.reset();
    440     network_state_handler_->RemoveObserver(test_observer_.get(), FROM_HERE);
    441     network_state_handler_.reset();
    442     DBusThreadManager::Shutdown();
    443   }
    444 
    445   void SuccessCallback(const std::string& callback_name) {
    446     success_callback_name_ = callback_name;
    447   }
    448 
    449   void GetPropertiesCallback(const std::string& service_path,
    450                              const base::DictionaryValue& dictionary) {
    451     get_properties_path_ = service_path;
    452     get_properties_.reset(dictionary.DeepCopy());
    453   }
    454 
    455   void CreateConfigurationCallback(const std::string& service_path) {
    456     create_service_path_ = service_path;
    457   }
    458 
    459  protected:
    460   bool GetServiceStringProperty(const std::string& service_path,
    461                                 const std::string& key,
    462                                 std::string* result) {
    463     ShillServiceClient::TestInterface* service_test =
    464         DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
    465     const base::DictionaryValue* properties =
    466         service_test->GetServiceProperties(service_path);
    467     if (properties && properties->GetStringWithoutPathExpansion(key, result))
    468       return true;
    469     return false;
    470   }
    471 
    472   bool GetReceivedStringProperty(const std::string& service_path,
    473                                  const std::string& key,
    474                                  std::string* result) {
    475     if (get_properties_path_ != service_path)
    476       return false;
    477     if (get_properties_ &&
    478         get_properties_->GetStringWithoutPathExpansion(key, result))
    479       return true;
    480     return false;
    481   }
    482 
    483   scoped_ptr<NetworkStateHandler> network_state_handler_;
    484   scoped_ptr<NetworkConfigurationHandler> network_configuration_handler_;
    485   scoped_ptr<TestObserver> test_observer_;
    486   base::MessageLoopForUI message_loop_;
    487   std::string success_callback_name_;
    488   std::string get_properties_path_;
    489   scoped_ptr<DictionaryValue> get_properties_;
    490   std::string create_service_path_;
    491 };
    492 
    493 TEST_F(NetworkConfigurationHandlerStubTest, StubSetAndClearProperties) {
    494   // TODO(stevenjb): Remove dependency on default Stub service.
    495   const std::string service_path("wifi1");
    496   const std::string test_identity("test_identity");
    497   const std::string test_passphrase("test_passphrase");
    498 
    499   // Set Properties
    500   base::DictionaryValue properties_to_set;
    501   properties_to_set.SetStringWithoutPathExpansion(
    502       flimflam::kIdentityProperty, test_identity);
    503   properties_to_set.SetStringWithoutPathExpansion(
    504       flimflam::kPassphraseProperty, test_passphrase);
    505   network_configuration_handler_->SetProperties(
    506       service_path,
    507       properties_to_set,
    508       base::Bind(
    509           &NetworkConfigurationHandlerStubTest::SuccessCallback,
    510           base::Unretained(this), "SetProperties"),
    511       base::Bind(&ErrorCallback, false, service_path));
    512   message_loop_.RunUntilIdle();
    513 
    514   EXPECT_EQ("SetProperties", success_callback_name_);
    515   std::string identity, passphrase;
    516   EXPECT_TRUE(GetServiceStringProperty(
    517       service_path, flimflam::kIdentityProperty, &identity));
    518   EXPECT_TRUE(GetServiceStringProperty(
    519       service_path, flimflam::kPassphraseProperty, &passphrase));
    520   EXPECT_EQ(test_identity, identity);
    521   EXPECT_EQ(test_passphrase, passphrase);
    522   EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(service_path));
    523 
    524   // Clear Properties
    525   std::vector<std::string> properties_to_clear;
    526   properties_to_clear.push_back(flimflam::kIdentityProperty);
    527   properties_to_clear.push_back(flimflam::kPassphraseProperty);
    528   network_configuration_handler_->ClearProperties(
    529       service_path,
    530       properties_to_clear,
    531       base::Bind(
    532           &NetworkConfigurationHandlerStubTest::SuccessCallback,
    533           base::Unretained(this), "ClearProperties"),
    534       base::Bind(&ErrorCallback, false, service_path));
    535   message_loop_.RunUntilIdle();
    536 
    537   EXPECT_EQ("ClearProperties", success_callback_name_);
    538   EXPECT_FALSE(GetServiceStringProperty(
    539       service_path, flimflam::kIdentityProperty, &identity));
    540   EXPECT_FALSE(GetServiceStringProperty(
    541       service_path, flimflam::kIdentityProperty, &passphrase));
    542   EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(service_path));
    543 }
    544 
    545 TEST_F(NetworkConfigurationHandlerStubTest, StubGetNameFromWifiHex) {
    546   // TODO(stevenjb): Remove dependency on default Stub service.
    547   const std::string service_path("wifi1");
    548   std::string wifi_hex = "5468697320697320484558205353494421";
    549   std::string expected_name = "This is HEX SSID!";
    550 
    551   // Set Properties
    552   base::DictionaryValue properties_to_set;
    553   properties_to_set.SetStringWithoutPathExpansion(
    554       flimflam::kWifiHexSsid, wifi_hex);
    555   network_configuration_handler_->SetProperties(
    556       service_path,
    557       properties_to_set,
    558       base::Bind(&base::DoNothing),
    559       base::Bind(&ErrorCallback, false, service_path));
    560   message_loop_.RunUntilIdle();
    561   std::string wifi_hex_result;
    562   EXPECT_TRUE(GetServiceStringProperty(
    563       service_path, flimflam::kWifiHexSsid, &wifi_hex_result));
    564   EXPECT_EQ(wifi_hex, wifi_hex_result);
    565 
    566   // Get Properties
    567   network_configuration_handler_->GetProperties(
    568       service_path,
    569       base::Bind(&NetworkConfigurationHandlerStubTest::GetPropertiesCallback,
    570                  base::Unretained(this)),
    571       base::Bind(&ErrorCallback, false, service_path));
    572   message_loop_.RunUntilIdle();
    573 
    574   EXPECT_EQ(service_path, get_properties_path_);
    575   std::string name_result;
    576   EXPECT_TRUE(GetReceivedStringProperty(
    577       service_path, flimflam::kNameProperty, &name_result));
    578   EXPECT_EQ(expected_name, name_result);
    579 }
    580 
    581 TEST_F(NetworkConfigurationHandlerStubTest, StubCreateConfiguration) {
    582   const std::string service_path("test_wifi");
    583   base::DictionaryValue properties;
    584   properties.SetStringWithoutPathExpansion(
    585       flimflam::kSSIDProperty, service_path);
    586   properties.SetStringWithoutPathExpansion(
    587       flimflam::kNameProperty, service_path);
    588   properties.SetStringWithoutPathExpansion(
    589       flimflam::kGuidProperty, service_path);
    590   properties.SetStringWithoutPathExpansion(
    591       flimflam::kTypeProperty, flimflam::kTypeWifi);
    592   properties.SetStringWithoutPathExpansion(
    593       flimflam::kStateProperty, flimflam::kStateIdle);
    594   properties.SetStringWithoutPathExpansion(
    595       flimflam::kProfileProperty, ShillProfileClientStub::kSharedProfilePath);
    596 
    597   network_configuration_handler_->CreateConfiguration(
    598       properties,
    599       base::Bind(
    600           &NetworkConfigurationHandlerStubTest::CreateConfigurationCallback,
    601           base::Unretained(this)),
    602       base::Bind(&ErrorCallback, false, service_path));
    603   message_loop_.RunUntilIdle();
    604 
    605   EXPECT_FALSE(create_service_path_.empty());
    606 
    607   std::string ssid;
    608   EXPECT_TRUE(GetServiceStringProperty(
    609       create_service_path_, flimflam::kSSIDProperty, &ssid));
    610   std::string actual_profile;
    611   EXPECT_EQ(service_path, ssid);
    612 
    613   EXPECT_TRUE(GetServiceStringProperty(
    614       create_service_path_, flimflam::kProfileProperty, &actual_profile));
    615   EXPECT_EQ(ShillProfileClientStub::kSharedProfilePath, actual_profile);
    616 }
    617 
    618 }  // namespace chromeos
    619