148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood// Copyright (c) 2012 The Chromium Authors. All rights reserved.
248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood// Use of this source code is governed by a BSD-style license that can be
348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood// found in the LICENSE file.
448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood#include "base/bind.h"
648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood#include "base/json/json_writer.h"
748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood#include "base/message_loop/message_loop.h"
848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood#include "base/strings/string_piece.h"
948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood#include "base/values.h"
1048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood#include "chromeos/dbus/dbus_thread_manager.h"
1148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood#include "chromeos/dbus/fake_dbus_thread_manager.h"
1248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood#include "chromeos/dbus/mock_shill_manager_client.h"
1348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood#include "chromeos/dbus/mock_shill_profile_client.h"
1448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood#include "chromeos/dbus/mock_shill_service_client.h"
1548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood#include "chromeos/dbus/shill_stub_helper.h"
1648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood#include "chromeos/network/network_configuration_handler.h"
1748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood#include "chromeos/network/network_state.h"
1848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood#include "chromeos/network/network_state_handler.h"
1948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood#include "chromeos/network/network_state_handler_observer.h"
2048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood#include "chromeos/network/shill_property_util.h"
2148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood#include "testing/gmock/include/gmock/gmock.h"
2248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood#include "testing/gtest/include/gtest/gtest.h"
2348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood#include "third_party/cros_system_api/dbus/service_constants.h"
2448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
2548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodusing ::testing::_;
2648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodusing ::testing::AnyNumber;
2748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodusing ::testing::Invoke;
2848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodusing ::testing::Pointee;
2948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodusing ::testing::Return;
3048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodusing ::testing::SaveArg;
3148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodusing ::testing::StrEq;
3248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
3348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood// Matcher to match base::Value.
3448ded2421114c4c87ef3f8005c9f793a5d077cbdMike LockwoodMATCHER_P(IsEqualTo, value, "") { return arg.Equals(value); }
3548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
3648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodnamespace chromeos {
3748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
3848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodnamespace {
3948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
4048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodstatic std::string PrettyJson(const base::DictionaryValue& value) {
4148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  std::string pretty;
4248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  base::JSONWriter::WriteWithOptions(&value,
4348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood                                     base::JSONWriter::OPTIONS_PRETTY_PRINT,
4448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood                                     &pretty);
4548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  return pretty;
4648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood}
4748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
4848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodvoid DictionaryValueCallback(
4948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    const std::string& expected_id,
5048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    const std::string& expected_json,
5148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    const std::string& service_path,
5248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    const base::DictionaryValue& dictionary) {
5348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  std::string dict_str = PrettyJson(dictionary);
5448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  EXPECT_EQ(expected_json, dict_str);
5548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  EXPECT_EQ(expected_id, service_path);
5648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood}
5748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
5848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodvoid ErrorCallback(bool error_expected,
5948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood                   const std::string& expected_id,
6048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood                   const std::string& error_name,
6148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood                   scoped_ptr<base::DictionaryValue> error_data) {
6248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  EXPECT_TRUE(error_expected) << "Unexpected error: " << error_name
6348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood      << " with associated data: \n"
6448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood      << PrettyJson(*error_data);
6548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood}
6648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
6748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodvoid StringResultCallback(const std::string& expected_result,
6848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood                          const std::string& result) {
6948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  EXPECT_EQ(expected_result, result);
7048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood}
7148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
7248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodvoid DBusErrorCallback(const std::string& error_name,
7348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood                       const std::string& error_message) {
7448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  EXPECT_TRUE(false) << "DBus Error: " << error_name << "("
7548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood      << error_message << ")";
7648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood}
7748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
7848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodclass TestCallback {
7948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public:
8048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  TestCallback() : run_count_(0) {}
8148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  void Run() {
8248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    ++run_count_;
8348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  }
8448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  int run_count() const { return run_count_; }
8548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
8648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood private:
8748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  int run_count_;
8848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood};
8948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
9048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood}  // namespace
9148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
9248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwoodclass NetworkConfigurationHandlerTest : public testing::Test {
9348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood public:
9448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  NetworkConfigurationHandlerTest()
9548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood      : mock_manager_client_(NULL),
9648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood        mock_profile_client_(NULL),
9748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood        mock_service_client_(NULL),
9848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood        dictionary_value_result_(NULL) {}
9948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  virtual ~NetworkConfigurationHandlerTest() {}
10048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
10148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  virtual void SetUp() OVERRIDE {
10248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    FakeDBusThreadManager* dbus_thread_manager = new FakeDBusThreadManager;
10348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    mock_manager_client_ = new MockShillManagerClient();
10448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    mock_profile_client_ = new MockShillProfileClient();
10548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    mock_service_client_ = new MockShillServiceClient();
10648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    dbus_thread_manager->SetShillManagerClient(
10748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood        scoped_ptr<ShillManagerClient>(mock_manager_client_).Pass());
10848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    dbus_thread_manager->SetShillProfileClient(
10948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood        scoped_ptr<ShillProfileClient>(mock_profile_client_).Pass());
11048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    dbus_thread_manager->SetShillServiceClient(
11148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood        scoped_ptr<ShillServiceClient>(mock_service_client_).Pass());
11248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
11348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    EXPECT_CALL(*mock_service_client_, GetProperties(_, _))
11448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood        .Times(AnyNumber());
11548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    EXPECT_CALL(*mock_manager_client_, GetProperties(_))
11648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood        .Times(AnyNumber());
11748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    EXPECT_CALL(*mock_manager_client_, AddPropertyChangedObserver(_))
11848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood        .Times(AnyNumber());
11948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    EXPECT_CALL(*mock_manager_client_, RemovePropertyChangedObserver(_))
12048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood        .Times(AnyNumber());
12148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
12248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    DBusThreadManager::InitializeForTesting(dbus_thread_manager);
12348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
12448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    network_state_handler_.reset(NetworkStateHandler::InitializeForTest());
12548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    network_configuration_handler_.reset(new NetworkConfigurationHandler());
12648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    network_configuration_handler_->Init(network_state_handler_.get());
12748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    message_loop_.RunUntilIdle();
12848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  }
12948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
13048ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  virtual void TearDown() OVERRIDE {
13148ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    network_configuration_handler_.reset();
13248ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    network_state_handler_.reset();
13348ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood    DBusThreadManager::Shutdown();
13448ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  }
13548ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood
13648ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  // Handles responses for GetProperties method calls.
13748ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood  void OnGetProperties(
13848ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood      const dbus::ObjectPath& path,
13948ded2421114c4c87ef3f8005c9f793a5d077cbdMike Lockwood      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
214TEST_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
249TEST_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
271TEST_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
308TEST_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
346TEST_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));
354
355  EXPECT_CALL(*mock_manager_client_,
356              ConfigureServiceForProfile(dbus::ObjectPath(profile), _, _, _))
357      .WillOnce(
358           Invoke(this, &NetworkConfigurationHandlerTest::OnConfigureService));
359  network_configuration_handler_->CreateConfiguration(
360      value,
361      base::Bind(&StringResultCallback, std::string("/service/2")),
362      base::Bind(&ErrorCallback, false, std::string("")));
363  message_loop_.RunUntilIdle();
364}
365
366TEST_F(NetworkConfigurationHandlerTest, RemoveConfiguration) {
367  std::string service_path = "/service/1";
368
369  TestCallback test_callback;
370  EXPECT_CALL(
371      *mock_service_client_,
372      GetLoadableProfileEntries(_, _)).WillOnce(Invoke(
373          this,
374          &NetworkConfigurationHandlerTest::OnGetLoadableProfileEntries));
375  EXPECT_CALL(
376      *mock_profile_client_,
377      DeleteEntry(_, _, _, _)).WillRepeatedly(Invoke(
378          this,
379          &NetworkConfigurationHandlerTest::OnDeleteEntry));
380
381  network_configuration_handler_->RemoveConfiguration(
382      service_path,
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));
388}
389
390////////////////////////////////////////////////////////////////////////////////
391// Stub based tests
392
393namespace {
394
395class TestObserver : public chromeos::NetworkStateHandlerObserver {
396 public:
397  TestObserver() : network_list_changed_count_(0) {}
398  virtual ~TestObserver() {}
399
400  virtual void NetworkListChanged() OVERRIDE {
401    ++network_list_changed_count_;
402  }
403
404  virtual void NetworkPropertiesUpdated(const NetworkState* network) OVERRIDE {
405    property_updates_[network->path()]++;
406  }
407
408  size_t network_list_changed_count() { return network_list_changed_count_; }
409
410  int PropertyUpdatesForService(const std::string& service_path) {
411    return property_updates_[service_path];
412  }
413
414  void ClearPropertyUpdates() {
415    property_updates_.clear();
416  }
417
418 private:
419  size_t network_list_changed_count_;
420  std::map<std::string, int> property_updates_;
421
422  DISALLOW_COPY_AND_ASSIGN(TestObserver);
423};
424
425}  // namespace
426
427class NetworkConfigurationHandlerStubTest : public testing::Test {
428 public:
429  NetworkConfigurationHandlerStubTest()  {
430  }
431
432  virtual ~NetworkConfigurationHandlerStubTest() {
433  }
434
435  virtual void SetUp() OVERRIDE {
436    DBusThreadManager::InitializeWithStub();
437
438    network_state_handler_.reset(NetworkStateHandler::InitializeForTest());
439    test_observer_.reset(new TestObserver());
440    network_state_handler_->AddObserver(test_observer_.get(), FROM_HERE);
441
442    network_configuration_handler_.reset(new NetworkConfigurationHandler());
443    network_configuration_handler_->Init(network_state_handler_.get());
444
445    message_loop_.RunUntilIdle();
446    test_observer_->ClearPropertyUpdates();
447  }
448
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();
454  }
455
456  void SuccessCallback(const std::string& callback_name) {
457    success_callback_name_ = callback_name;
458  }
459
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());
464  }
465
466  void CreateConfigurationCallback(const std::string& service_path) {
467    create_service_path_ = service_path;
468  }
469
470 protected:
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))
479      return true;
480    return false;
481  }
482
483  bool GetReceivedStringProperty(const std::string& service_path,
484                                 const std::string& key,
485                                 std::string* result) {
486    if (get_properties_path_ != service_path)
487      return false;
488    if (get_properties_ &&
489        get_properties_->GetStringWithoutPathExpansion(key, result))
490      return true;
491    return false;
492  }
493
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<DictionaryValue> get_properties_;
501  std::string create_service_path_;
502};
503
504TEST_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");
509
510  // Set Properties
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(
517      service_path,
518      properties_to_set,
519      base::Bind(
520          &NetworkConfigurationHandlerStubTest::SuccessCallback,
521          base::Unretained(this), "SetProperties"),
522      base::Bind(&ErrorCallback, false, service_path));
523  message_loop_.RunUntilIdle();
524
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));
534
535  // Clear Properties
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(
540      service_path,
541      properties_to_clear,
542      base::Bind(
543          &NetworkConfigurationHandlerStubTest::SuccessCallback,
544          base::Unretained(this), "ClearProperties"),
545      base::Bind(&ErrorCallback, false, service_path));
546  message_loop_.RunUntilIdle();
547
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));
554}
555
556TEST_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!";
561
562  // Set Properties
563  base::DictionaryValue properties_to_set;
564  properties_to_set.SetStringWithoutPathExpansion(
565      shill::kWifiHexSsid, wifi_hex);
566  network_configuration_handler_->SetProperties(
567      service_path,
568      properties_to_set,
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);
576
577  // Get Properties
578  network_configuration_handler_->GetProperties(
579      service_path,
580      base::Bind(&NetworkConfigurationHandlerStubTest::GetPropertiesCallback,
581                 base::Unretained(this)),
582      base::Bind(&ErrorCallback, false, service_path));
583  message_loop_.RunUntilIdle();
584
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);
590}
591
592TEST_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);
604
605  network_configuration_handler_->CreateConfiguration(
606      properties,
607      base::Bind(
608          &NetworkConfigurationHandlerStubTest::CreateConfigurationCallback,
609          base::Unretained(this)),
610      base::Bind(&ErrorCallback, false, service_path));
611  message_loop_.RunUntilIdle();
612
613  EXPECT_FALSE(create_service_path_.empty());
614
615  std::string guid;
616  EXPECT_TRUE(GetServiceStringProperty(
617      create_service_path_, shill::kGuidProperty, &guid));
618  EXPECT_EQ(service_path, guid);
619
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);
624}
625
626}  // namespace chromeos
627