network_configuration_handler_unittest.cc revision 9ab5563a3196760eb381d102cbb2bc0f7abc6a50
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/network/network_configuration_handler.h"
16#include "chromeos/network/network_state_handler.h"
17#include "testing/gmock/include/gmock/gmock.h"
18#include "testing/gtest/include/gtest/gtest.h"
19
20using ::testing::_;
21using ::testing::Invoke;
22using ::testing::Pointee;
23using ::testing::Return;
24using ::testing::SaveArg;
25using ::testing::StrEq;
26
27// Matcher to match base::Value.
28MATCHER_P(IsEqualTo, value, "") { return arg.Equals(value); }
29
30namespace chromeos {
31
32namespace {
33
34static std::string PrettyJson(const base::DictionaryValue& value) {
35  std::string pretty;
36  base::JSONWriter::WriteWithOptions(&value,
37                                     base::JSONWriter::OPTIONS_PRETTY_PRINT,
38                                     &pretty);
39  return pretty;
40}
41
42void DictionaryValueCallback(
43    const std::string& expected_id,
44    const std::string& expected_json,
45    const std::string& service_path,
46    const base::DictionaryValue& dictionary) {
47  std::string dict_str = PrettyJson(dictionary);
48  EXPECT_EQ(expected_json, dict_str);
49  EXPECT_EQ(expected_id, service_path);
50}
51
52void ErrorCallback(bool error_expected,
53                   const std::string& expected_id,
54                   const std::string& error_name,
55                   scoped_ptr<base::DictionaryValue> error_data) {
56  EXPECT_TRUE(error_expected) << "Unexpected error: " << error_name
57      << " with associated data: \n"
58      << PrettyJson(*error_data);
59}
60
61void StringResultCallback(const std::string& expected_result,
62                          const std::string& result) {
63  EXPECT_EQ(expected_result, result);
64}
65
66void DBusErrorCallback(const std::string& error_name,
67                       const std::string& error_message) {
68  EXPECT_TRUE(false) << "DBus Error: " << error_name << "("
69      << error_message << ")";
70}
71
72class TestCallback {
73 public:
74  TestCallback() : run_count_(0) {}
75  void Run() {
76    ++run_count_;
77  }
78  int run_count() const { return run_count_; }
79
80 private:
81  int run_count_;
82};
83
84}  // namespace
85
86class NetworkConfigurationHandlerTest : public testing::Test {
87 public:
88  NetworkConfigurationHandlerTest()
89      : mock_manager_client_(NULL),
90        mock_profile_client_(NULL),
91        mock_service_client_(NULL),
92        dictionary_value_result_(NULL) {}
93  virtual ~NetworkConfigurationHandlerTest() {}
94
95  virtual void SetUp() OVERRIDE {
96    MockDBusThreadManager* mock_dbus_thread_manager = new MockDBusThreadManager;
97    EXPECT_CALL(*mock_dbus_thread_manager, GetSystemBus())
98    .WillRepeatedly(Return(reinterpret_cast<dbus::Bus*>(NULL)));
99    DBusThreadManager::InitializeForTesting(mock_dbus_thread_manager);
100    mock_manager_client_ =
101        mock_dbus_thread_manager->mock_shill_manager_client();
102    mock_profile_client_ =
103        mock_dbus_thread_manager->mock_shill_profile_client();
104    mock_service_client_ =
105        mock_dbus_thread_manager->mock_shill_service_client();
106
107    network_state_handler_.reset(NetworkStateHandler::InitializeForTest());
108    network_configuration_handler_.reset(new NetworkConfigurationHandler());
109    network_configuration_handler_->Init(network_state_handler_.get());
110    message_loop_.RunUntilIdle();
111  }
112
113  virtual void TearDown() OVERRIDE {
114    network_configuration_handler_.reset();
115    network_state_handler_.reset();
116    DBusThreadManager::Shutdown();
117  }
118
119  // Handles responses for GetProperties method calls.
120  void OnGetProperties(
121      const dbus::ObjectPath& path,
122      const ShillClientHelper::DictionaryValueCallback& callback) {
123    callback.Run(DBUS_METHOD_CALL_SUCCESS, *dictionary_value_result_);
124  }
125
126  // Handles responses for SetProperties method calls.
127  void OnSetProperties(const dbus::ObjectPath& service_path,
128                       const base::DictionaryValue& properties,
129                       const base::Closure& callback,
130                       const ShillClientHelper::ErrorCallback& error_callback) {
131    callback.Run();
132  }
133
134  // Handles responses for ClearProperties method calls.
135  void OnClearProperties(
136      const dbus::ObjectPath& service_path,
137      const std::vector<std::string>& names,
138      const ShillClientHelper::ListValueCallback& callback,
139      const ShillClientHelper::ErrorCallback& error_callback) {
140    base::ListValue result;
141    result.AppendBoolean(true);
142    callback.Run(result);
143  }
144
145  // Handles responses for ClearProperties method calls, and simulates an error
146  // result.
147  void OnClearPropertiesError(
148      const dbus::ObjectPath& service_path,
149      const std::vector<std::string>& names,
150      const ShillClientHelper::ListValueCallback& callback,
151      const ShillClientHelper::ErrorCallback& error_callback) {
152    base::ListValue result;
153    result.AppendBoolean(false);
154    callback.Run(result);
155  }
156
157  void OnConfigureService(const base::DictionaryValue& properties,
158                    const ObjectPathCallback& callback,
159                    const ShillClientHelper::ErrorCallback& error_callback) {
160    callback.Run(dbus::ObjectPath("/service/2"));
161  }
162
163  void OnGetLoadableProfileEntries(
164      const dbus::ObjectPath& service_path,
165      const ShillClientHelper::DictionaryValueCallback& callback) {
166    base::DictionaryValue entries;
167    entries.SetString("profile1", "entry1");
168    entries.SetString("profile2", "entry2");
169    callback.Run(DBUS_METHOD_CALL_SUCCESS, entries);
170  }
171
172  void OnDeleteEntry(const dbus::ObjectPath& profile_path,
173                     const std::string& entry_path,
174                     const base::Closure& callback,
175                     const ShillClientHelper::ErrorCallback& error_callback) {
176    // Don't run the callback immediately to emulate actual behavior.
177    message_loop_.PostTask(FROM_HERE, callback);
178  }
179
180  bool PendingProfileEntryDeleterForTest(const std::string& service_path) {
181    return network_configuration_handler_->
182        PendingProfileEntryDeleterForTest(service_path);
183  }
184
185 protected:
186  MockShillManagerClient* mock_manager_client_;
187  MockShillProfileClient* mock_profile_client_;
188  MockShillServiceClient* mock_service_client_;
189  scoped_ptr<NetworkStateHandler> network_state_handler_;
190  scoped_ptr<NetworkConfigurationHandler> network_configuration_handler_;
191  base::MessageLoop message_loop_;
192  base::DictionaryValue* dictionary_value_result_;
193};
194
195TEST_F(NetworkConfigurationHandlerTest, GetProperties) {
196  std::string service_path = "/service/1";
197  std::string expected_json = "{\n   \"SSID\": \"MyNetwork\"\n}\n";
198  std::string networkName = "MyNetwork";
199  std::string key = "SSID";
200  scoped_ptr<base::StringValue> networkNameValue(
201      base::Value::CreateStringValue(networkName));
202
203  base::DictionaryValue value;
204  value.Set(key, base::Value::CreateStringValue(networkName));
205  dictionary_value_result_ = &value;
206  EXPECT_CALL(*mock_service_client_,
207              SetProperty(dbus::ObjectPath(service_path), key,
208                          IsEqualTo(networkNameValue.get()), _, _)).Times(1);
209  DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
210      dbus::ObjectPath(service_path), key, *networkNameValue,
211      base::Bind(&base::DoNothing),
212      base::Bind(&DBusErrorCallback));
213  message_loop_.RunUntilIdle();
214
215  ShillServiceClient::DictionaryValueCallback get_properties_callback;
216  EXPECT_CALL(*mock_service_client_,
217              GetProperties(_, _)).WillOnce(
218                  Invoke(this,
219                         &NetworkConfigurationHandlerTest::OnGetProperties));
220  network_configuration_handler_->GetProperties(
221      service_path,
222      base::Bind(&DictionaryValueCallback,
223                 service_path,
224                 expected_json),
225                 base::Bind(&ErrorCallback, false, service_path));
226  message_loop_.RunUntilIdle();
227}
228
229TEST_F(NetworkConfigurationHandlerTest, SetProperties) {
230  std::string service_path = "/service/1";
231  std::string networkName = "MyNetwork";
232  std::string key = "SSID";
233  scoped_ptr<base::StringValue> networkNameValue(
234      base::Value::CreateStringValue(networkName));
235
236  base::DictionaryValue value;
237  value.Set(key, base::Value::CreateStringValue(networkName));
238  dictionary_value_result_ = &value;
239  EXPECT_CALL(*mock_service_client_,
240              SetProperties(_, _, _, _)).WillOnce(
241                  Invoke(this,
242                         &NetworkConfigurationHandlerTest::OnSetProperties));
243  network_configuration_handler_->SetProperties(
244      service_path,
245      value,
246      base::Bind(&base::DoNothing),
247      base::Bind(&ErrorCallback, false, service_path));
248  message_loop_.RunUntilIdle();
249}
250
251TEST_F(NetworkConfigurationHandlerTest, ClearProperties) {
252  std::string service_path = "/service/1";
253  std::string networkName = "MyNetwork";
254  std::string key = "SSID";
255  scoped_ptr<base::StringValue> networkNameValue(
256      base::Value::CreateStringValue(networkName));
257
258  // First set up a value to clear.
259  base::DictionaryValue value;
260  value.Set(key, base::Value::CreateStringValue(networkName));
261  dictionary_value_result_ = &value;
262  EXPECT_CALL(*mock_service_client_,
263              SetProperties(_, _, _, _)).WillOnce(
264                  Invoke(this,
265                         &NetworkConfigurationHandlerTest::OnSetProperties));
266  network_configuration_handler_->SetProperties(
267      service_path,
268      value,
269      base::Bind(&base::DoNothing),
270      base::Bind(&ErrorCallback, false, service_path));
271  message_loop_.RunUntilIdle();
272
273  // Now clear it.
274  std::vector<std::string> values_to_clear;
275  values_to_clear.push_back(key);
276  EXPECT_CALL(*mock_service_client_,
277              ClearProperties(_, _, _, _)).WillOnce(
278                  Invoke(this,
279                         &NetworkConfigurationHandlerTest::OnClearProperties));
280  network_configuration_handler_->ClearProperties(
281      service_path,
282      values_to_clear,
283      base::Bind(&base::DoNothing),
284      base::Bind(&ErrorCallback, false, service_path));
285  message_loop_.RunUntilIdle();
286}
287
288TEST_F(NetworkConfigurationHandlerTest, ClearPropertiesError) {
289  std::string service_path = "/service/1";
290  std::string networkName = "MyNetwork";
291  std::string key = "SSID";
292  scoped_ptr<base::StringValue> networkNameValue(
293      base::Value::CreateStringValue(networkName));
294
295  // First set up a value to clear.
296  base::DictionaryValue value;
297  value.Set(key, base::Value::CreateStringValue(networkName));
298  dictionary_value_result_ = &value;
299  EXPECT_CALL(*mock_service_client_,
300              SetProperties(_, _, _, _)).WillOnce(
301                  Invoke(this,
302                         &NetworkConfigurationHandlerTest::OnSetProperties));
303  network_configuration_handler_->SetProperties(
304      service_path,
305      value,
306      base::Bind(&base::DoNothing),
307      base::Bind(&ErrorCallback, false, service_path));
308  message_loop_.RunUntilIdle();
309
310  // Now clear it.
311  std::vector<std::string> values_to_clear;
312  values_to_clear.push_back(key);
313  EXPECT_CALL(
314      *mock_service_client_,
315      ClearProperties(_, _, _, _)).WillOnce(
316          Invoke(this,
317                 &NetworkConfigurationHandlerTest::OnClearPropertiesError));
318  network_configuration_handler_->ClearProperties(
319      service_path,
320      values_to_clear,
321      base::Bind(&base::DoNothing),
322      base::Bind(&ErrorCallback, true, service_path));
323  message_loop_.RunUntilIdle();
324}
325
326TEST_F(NetworkConfigurationHandlerTest, CreateConfiguration) {
327  std::string expected_json = "{\n   \"SSID\": \"MyNetwork\"\n}\n";
328  std::string networkName = "MyNetwork";
329  std::string key = "SSID";
330  scoped_ptr<base::StringValue> networkNameValue(
331      base::Value::CreateStringValue(networkName));
332  base::DictionaryValue value;
333  value.Set(key, base::Value::CreateStringValue(networkName));
334
335  EXPECT_CALL(
336      *mock_manager_client_,
337      ConfigureService(_, _, _)).WillOnce(
338          Invoke(this,
339                 &NetworkConfigurationHandlerTest::OnConfigureService));
340  network_configuration_handler_->CreateConfiguration(
341      value,
342      base::Bind(&StringResultCallback, std::string("/service/2")),
343      base::Bind(&ErrorCallback, false, std::string("")));
344  message_loop_.RunUntilIdle();
345}
346
347TEST_F(NetworkConfigurationHandlerTest, RemoveConfiguration) {
348  std::string service_path = "/service/1";
349
350  TestCallback test_callback;
351  EXPECT_CALL(
352      *mock_service_client_,
353      GetLoadableProfileEntries(_, _)).WillOnce(Invoke(
354          this,
355          &NetworkConfigurationHandlerTest::OnGetLoadableProfileEntries));
356  EXPECT_CALL(
357      *mock_profile_client_,
358      DeleteEntry(_, _, _, _)).WillRepeatedly(Invoke(
359          this,
360          &NetworkConfigurationHandlerTest::OnDeleteEntry));
361
362  network_configuration_handler_->RemoveConfiguration(
363      service_path,
364      base::Bind(&TestCallback::Run, base::Unretained(&test_callback)),
365      base::Bind(&ErrorCallback, false, service_path));
366  message_loop_.RunUntilIdle();
367  EXPECT_EQ(1, test_callback.run_count());
368  EXPECT_FALSE(PendingProfileEntryDeleterForTest(service_path));
369}
370
371}  // namespace chromeos
372