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/values.h"
7#include "chromeos/dbus/shill_client_unittest_base.h"
8#include "chromeos/dbus/shill_manager_client.h"
9#include "dbus/message.h"
10#include "dbus/object_path.h"
11#include "dbus/values_util.h"
12#include "testing/gtest/include/gtest/gtest.h"
13#include "third_party/cros_system_api/dbus/service_constants.h"
14
15using testing::_;
16using testing::ByRef;
17
18namespace chromeos {
19
20namespace {
21
22void ExpectStringArguments(const std::vector<std::string>& arguments,
23                           dbus::MessageReader* reader) {
24  for (std::vector<std::string>::const_iterator iter = arguments.begin();
25       iter != arguments.end(); ++iter) {
26    std::string arg_string;
27    ASSERT_TRUE(reader->PopString(&arg_string));
28    EXPECT_EQ(*iter, arg_string);
29  }
30  EXPECT_FALSE(reader->HasMoreData());
31}
32
33void ExpectStringArgumentsFollowedByObjectPath(
34      const std::vector<std::string>& arguments,
35      const dbus::ObjectPath& object_path,
36      dbus::MessageReader* reader) {
37  for (std::vector<std::string>::const_iterator iter = arguments.begin();
38       iter != arguments.end(); ++iter) {
39    std::string arg_string;
40    ASSERT_TRUE(reader->PopString(&arg_string));
41    EXPECT_EQ(*iter, arg_string);
42  }
43  dbus::ObjectPath path;
44  ASSERT_TRUE(reader->PopObjectPath(&path));
45  EXPECT_EQ(object_path, path);
46  EXPECT_FALSE(reader->HasMoreData());
47}
48
49
50}  // namespace
51
52class ShillManagerClientTest : public ShillClientUnittestBase {
53 public:
54  ShillManagerClientTest()
55      : ShillClientUnittestBase(shill::kFlimflamManagerInterface,
56                                dbus::ObjectPath(shill::kFlimflamServicePath)) {
57  }
58
59  virtual void SetUp() {
60    ShillClientUnittestBase::SetUp();
61    // Create a client with the mock bus.
62    client_.reset(ShillManagerClient::Create());
63    client_->Init(mock_bus_.get());
64    // Run the message loop to run the signal connection result callback.
65    message_loop_.RunUntilIdle();
66  }
67
68  virtual void TearDown() {
69    ShillClientUnittestBase::TearDown();
70  }
71
72 protected:
73  scoped_ptr<ShillManagerClient> client_;
74};
75
76TEST_F(ShillManagerClientTest, PropertyChanged) {
77  // Create a signal.
78  base::FundamentalValue kOfflineMode(true);
79  dbus::Signal signal(shill::kFlimflamManagerInterface,
80                      shill::kMonitorPropertyChanged);
81  dbus::MessageWriter writer(&signal);
82  writer.AppendString(shill::kOfflineModeProperty);
83  dbus::AppendBasicTypeValueData(&writer, kOfflineMode);
84
85  // Set expectations.
86  MockPropertyChangeObserver observer;
87  EXPECT_CALL(observer,
88              OnPropertyChanged(shill::kOfflineModeProperty,
89                                ValueEq(ByRef(kOfflineMode)))).Times(1);
90
91  // Add the observer
92  client_->AddPropertyChangedObserver(&observer);
93
94  // Run the signal callback.
95  SendPropertyChangedSignal(&signal);
96
97  // Remove the observer.
98  client_->RemovePropertyChangedObserver(&observer);
99
100  // Make sure it's not called anymore.
101  EXPECT_CALL(observer, OnPropertyChanged(_, _)).Times(0);
102
103  // Run the signal callback again and make sure the observer isn't called.
104  SendPropertyChangedSignal(&signal);
105}
106
107TEST_F(ShillManagerClientTest, GetProperties) {
108  // Create response.
109  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
110  dbus::MessageWriter writer(response.get());
111  dbus::MessageWriter array_writer(NULL);
112  writer.OpenArray("{sv}", &array_writer);
113  dbus::MessageWriter entry_writer(NULL);
114  array_writer.OpenDictEntry(&entry_writer);
115  entry_writer.AppendString(shill::kOfflineModeProperty);
116  entry_writer.AppendVariantOfBool(true);
117  array_writer.CloseContainer(&entry_writer);
118  writer.CloseContainer(&array_writer);
119
120  // Create the expected value.
121  base::DictionaryValue value;
122  value.SetWithoutPathExpansion(shill::kOfflineModeProperty,
123                                new base::FundamentalValue(true));
124  // Set expectations.
125  PrepareForMethodCall(shill::kGetPropertiesFunction,
126                       base::Bind(&ExpectNoArgument),
127                       response.get());
128  // Call method.
129  client_->GetProperties(base::Bind(&ExpectDictionaryValueResult, &value));
130  // Run the message loop.
131  message_loop_.RunUntilIdle();
132}
133
134TEST_F(ShillManagerClientTest, GetNetworksForGeolocation) {
135  // Create response.
136  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
137
138  dbus::MessageWriter writer(response.get());
139  dbus::MessageWriter type_dict_writer(NULL);
140  writer.OpenArray("{sv}", &type_dict_writer);
141  dbus::MessageWriter type_entry_writer(NULL);
142  type_dict_writer.OpenDictEntry(&type_entry_writer);
143  type_entry_writer.AppendString(shill::kTypeWifi);
144  dbus::MessageWriter variant_writer(NULL);
145  type_entry_writer.OpenVariant("aa{ss}", &variant_writer);
146  dbus::MessageWriter wap_list_writer(NULL);
147  variant_writer.OpenArray("a{ss}", &wap_list_writer);
148  dbus::MessageWriter property_dict_writer(NULL);
149  wap_list_writer.OpenArray("{ss}", &property_dict_writer);
150  dbus::MessageWriter property_entry_writer(NULL);
151  property_dict_writer.OpenDictEntry(&property_entry_writer);
152  property_entry_writer.AppendString(shill::kGeoMacAddressProperty);
153  property_entry_writer.AppendString("01:23:45:67:89:AB");
154  property_dict_writer.CloseContainer(&property_entry_writer);
155  wap_list_writer.CloseContainer(&property_dict_writer);
156  variant_writer.CloseContainer(&wap_list_writer);
157  type_entry_writer.CloseContainer(&wap_list_writer);
158  type_dict_writer.CloseContainer(&type_entry_writer);
159  writer.CloseContainer(&type_dict_writer);
160
161
162  // Create the expected value.
163  base::DictionaryValue type_dict_value;
164  base::ListValue* type_entry_value = new base::ListValue;
165  base::DictionaryValue* property_dict_value = new base::DictionaryValue;
166  property_dict_value->SetWithoutPathExpansion(
167      shill::kGeoMacAddressProperty,
168      new base::StringValue("01:23:45:67:89:AB"));
169  type_entry_value->Append(property_dict_value);
170  type_dict_value.SetWithoutPathExpansion("wifi", type_entry_value);
171
172  // Set expectations.
173  PrepareForMethodCall(shill::kGetNetworksForGeolocation,
174                       base::Bind(&ExpectNoArgument),
175                       response.get());
176  // Call method.
177  client_->GetNetworksForGeolocation(base::Bind(&ExpectDictionaryValueResult,
178                                                &type_dict_value));
179
180  // Run the message loop.
181  message_loop_.RunUntilIdle();
182}
183
184TEST_F(ShillManagerClientTest, SetProperty) {
185  // Create response.
186  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
187  // Set expectations.
188  base::StringValue value("portal list");
189  PrepareForMethodCall(shill::kSetPropertyFunction,
190                       base::Bind(ExpectStringAndValueArguments,
191                                  shill::kCheckPortalListProperty,
192                                  &value),
193                       response.get());
194  // Call method.
195  MockClosure mock_closure;
196  MockErrorCallback mock_error_callback;
197  client_->SetProperty(shill::kCheckPortalListProperty,
198                       value,
199                       mock_closure.GetCallback(),
200                       mock_error_callback.GetCallback());
201  EXPECT_CALL(mock_closure, Run()).Times(1);
202  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
203
204  // Run the message loop.
205  message_loop_.RunUntilIdle();
206}
207
208TEST_F(ShillManagerClientTest, RequestScan) {
209  // Create response.
210  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
211  // Set expectations.
212  PrepareForMethodCall(shill::kRequestScanFunction,
213                       base::Bind(&ExpectStringArgument, shill::kTypeWifi),
214                       response.get());
215  // Call method.
216  MockClosure mock_closure;
217  MockErrorCallback mock_error_callback;
218  client_->RequestScan(shill::kTypeWifi,
219                       mock_closure.GetCallback(),
220                       mock_error_callback.GetCallback());
221  EXPECT_CALL(mock_closure, Run()).Times(1);
222  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
223
224  // Run the message loop.
225  message_loop_.RunUntilIdle();
226}
227
228TEST_F(ShillManagerClientTest, EnableTechnology) {
229  // Create response.
230  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
231  // Set expectations.
232  PrepareForMethodCall(shill::kEnableTechnologyFunction,
233                       base::Bind(&ExpectStringArgument, shill::kTypeWifi),
234                       response.get());
235  // Call method.
236  MockClosure mock_closure;
237  MockErrorCallback mock_error_callback;
238  client_->EnableTechnology(shill::kTypeWifi,
239                            mock_closure.GetCallback(),
240                            mock_error_callback.GetCallback());
241  EXPECT_CALL(mock_closure, Run()).Times(1);
242  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
243
244  // Run the message loop.
245  message_loop_.RunUntilIdle();
246}
247
248TEST_F(ShillManagerClientTest, DisableTechnology) {
249  // Create response.
250  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
251  // Set expectations.
252  PrepareForMethodCall(shill::kDisableTechnologyFunction,
253                       base::Bind(&ExpectStringArgument, shill::kTypeWifi),
254                       response.get());
255  // Call method.
256  MockClosure mock_closure;
257  MockErrorCallback mock_error_callback;
258  client_->DisableTechnology(shill::kTypeWifi,
259                             mock_closure.GetCallback(),
260                             mock_error_callback.GetCallback());
261  EXPECT_CALL(mock_closure, Run()).Times(1);
262  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
263
264  // Run the message loop.
265  message_loop_.RunUntilIdle();
266}
267
268TEST_F(ShillManagerClientTest, ConfigureService) {
269  // Create response.
270  const dbus::ObjectPath object_path("/");
271  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
272  dbus::MessageWriter writer(response.get());
273  writer.AppendObjectPath(object_path);
274  // Create the argument dictionary.
275  scoped_ptr<base::DictionaryValue> arg(CreateExampleServiceProperties());
276  // Set expectations.
277  PrepareForMethodCall(shill::kConfigureServiceFunction,
278                       base::Bind(&ExpectDictionaryValueArgument, arg.get()),
279                       response.get());
280  // Call method.
281  MockErrorCallback mock_error_callback;
282  client_->ConfigureService(*arg,
283                            base::Bind(&ExpectObjectPathResultWithoutStatus,
284                                       object_path),
285                            mock_error_callback.GetCallback());
286  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
287
288  // Run the message loop.
289  message_loop_.RunUntilIdle();
290}
291
292TEST_F(ShillManagerClientTest, GetService) {
293  // Create response.
294  const dbus::ObjectPath object_path("/");
295  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
296  dbus::MessageWriter writer(response.get());
297  writer.AppendObjectPath(object_path);
298  // Create the argument dictionary.
299  scoped_ptr<base::DictionaryValue> arg(CreateExampleServiceProperties());
300  // Set expectations.
301  PrepareForMethodCall(shill::kGetServiceFunction,
302                       base::Bind(&ExpectDictionaryValueArgument, arg.get()),
303                       response.get());
304  // Call method.
305  MockErrorCallback mock_error_callback;
306  client_->GetService(*arg,
307                      base::Bind(&ExpectObjectPathResultWithoutStatus,
308                                 object_path),
309                      mock_error_callback.GetCallback());
310  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
311
312  // Run the message loop.
313  message_loop_.RunUntilIdle();
314}
315
316TEST_F(ShillManagerClientTest, VerifyDestination) {
317  // Create response.
318  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
319  dbus::MessageWriter writer(response.get());
320  bool expected = true;
321  writer.AppendBool(expected);
322  // Set expectations.
323  std::vector<std::string> arguments;
324  arguments.push_back("certificate");
325  arguments.push_back("public_key");
326  arguments.push_back("nonce");
327  arguments.push_back("signed_data");
328  arguments.push_back("device_serial");
329  arguments.push_back("device_ssid");
330  arguments.push_back("device_bssid");
331  PrepareForMethodCall(shill::kVerifyDestinationFunction,
332                       base::Bind(&ExpectStringArguments, arguments),
333                       response.get());
334
335  // Call method.
336  MockErrorCallback mock_error_callback;
337  ShillManagerClient::VerificationProperties properties;
338  properties.certificate = arguments[0];
339  properties.public_key = arguments[1];
340  properties.nonce = arguments[2];
341  properties.signed_data = arguments[3];
342  properties.device_serial = arguments[4];
343  properties.device_ssid = arguments[5];
344  properties.device_bssid = arguments[6];
345  client_->VerifyDestination(
346      properties,
347      base::Bind(&ExpectBoolResultWithoutStatus, expected),
348      mock_error_callback.GetCallback());
349  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
350
351  // Run the message loop.
352  message_loop_.RunUntilIdle();
353}
354
355TEST_F(ShillManagerClientTest, VerifyAndEncryptCredentials) {
356  // Create response.
357  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
358  dbus::MessageWriter writer(response.get());
359  std::string expected = "encrypted_credentials";
360  writer.AppendString(expected);
361  // Set expectations.
362  std::vector<std::string> arguments;
363  arguments.push_back("certificate");
364  arguments.push_back("public_key");
365  arguments.push_back("nonce");
366  arguments.push_back("signed_data");
367  arguments.push_back("device_serial");
368  arguments.push_back("device_ssid");
369  arguments.push_back("device_bssid");
370  std::string service_path = "/";
371  dbus::ObjectPath service_path_obj(service_path);
372  PrepareForMethodCall(shill::kVerifyAndEncryptCredentialsFunction,
373                       base::Bind(&ExpectStringArgumentsFollowedByObjectPath,
374                                  arguments,
375                                  service_path_obj),
376                       response.get());
377
378  // Call method.
379  MockErrorCallback mock_error_callback;
380  ShillManagerClient::VerificationProperties properties;
381  properties.certificate = arguments[0];
382  properties.public_key = arguments[1];
383  properties.nonce = arguments[2];
384  properties.signed_data = arguments[3];
385  properties.device_serial = arguments[4];
386  properties.device_ssid = arguments[5];
387  properties.device_bssid = arguments[6];
388  client_->VerifyAndEncryptCredentials(
389      properties,
390      service_path,
391      base::Bind(&ExpectStringResultWithoutStatus, expected),
392      mock_error_callback.GetCallback());
393  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
394
395  // Run the message loop.
396  message_loop_.RunUntilIdle();
397}
398
399TEST_F(ShillManagerClientTest, VerifyAndEncryptData) {
400  // Create response.
401  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
402  dbus::MessageWriter writer(response.get());
403  std::string expected = "encrypted_data";
404  writer.AppendString(expected);
405  // Set expectations.
406  std::vector<std::string> arguments;
407  arguments.push_back("certificate");
408  arguments.push_back("public_key");
409  arguments.push_back("nonce");
410  arguments.push_back("signed_data");
411  arguments.push_back("device_serial");
412  arguments.push_back("device_ssid");
413  arguments.push_back("device_bssid");
414  arguments.push_back("data");
415  PrepareForMethodCall(shill::kVerifyAndEncryptDataFunction,
416                       base::Bind(&ExpectStringArguments, arguments),
417                       response.get());
418
419  // Call method.
420  MockErrorCallback mock_error_callback;
421  ShillManagerClient::VerificationProperties properties;
422  properties.certificate = arguments[0];
423  properties.public_key = arguments[1];
424  properties.nonce = arguments[2];
425  properties.signed_data = arguments[3];
426  properties.device_serial = arguments[4];
427  properties.device_ssid = arguments[5];
428  properties.device_bssid = arguments[6];
429  client_->VerifyAndEncryptData(
430      properties,
431      arguments[7],
432      base::Bind(&ExpectStringResultWithoutStatus, expected),
433      mock_error_callback.GetCallback());
434  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
435
436  // Run the message loop.
437  message_loop_.RunUntilIdle();
438}
439
440}  // namespace chromeos
441