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_device_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
22const char kExampleDevicePath[] = "/foo/bar";
23
24// Expects the reader to have a string and a bool.
25void ExpectStringAndBoolArguments(const std::string& expected_string,
26                                  bool expected_bool,
27                                  dbus::MessageReader* reader) {
28  std::string arg1;
29  ASSERT_TRUE(reader->PopString(&arg1));
30  EXPECT_EQ(expected_string, arg1);
31  bool arg2 = false;
32  ASSERT_TRUE(reader->PopBool(&arg2));
33  EXPECT_EQ(expected_bool, arg2);
34  EXPECT_FALSE(reader->HasMoreData());
35}
36
37// Expects the reader to have two strings.
38void ExpectTwoStringArguments(const std::string& expected_string1,
39                              const std::string& expected_string2,
40                              dbus::MessageReader* reader) {
41  std::string arg1;
42  ASSERT_TRUE(reader->PopString(&arg1));
43  EXPECT_EQ(expected_string1, arg1);
44  std::string arg2;
45  ASSERT_TRUE(reader->PopString(&arg2));
46  EXPECT_EQ(expected_string2, arg2);
47  EXPECT_FALSE(reader->HasMoreData());
48}
49
50}  // namespace
51
52class ShillDeviceClientTest : public ShillClientUnittestBase {
53 public:
54  ShillDeviceClientTest()
55      : ShillClientUnittestBase(flimflam::kFlimflamDeviceInterface,
56                                   dbus::ObjectPath(kExampleDevicePath)) {
57  }
58
59  virtual void SetUp() {
60    ShillClientUnittestBase::SetUp();
61    // Create a client with the mock bus.
62    client_.reset(ShillDeviceClient::Create(REAL_DBUS_CLIENT_IMPLEMENTATION,
63                                            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<ShillDeviceClient> client_;
74};
75
76TEST_F(ShillDeviceClientTest, PropertyChanged) {
77  const bool kValue = true;
78  // Create a signal.
79  dbus::Signal signal(flimflam::kFlimflamDeviceInterface,
80                      flimflam::kMonitorPropertyChanged);
81  dbus::MessageWriter writer(&signal);
82  writer.AppendString(flimflam::kCellularAllowRoamingProperty);
83  writer.AppendVariantOfBool(kValue);
84
85  // Set expectations.
86  const base::FundamentalValue value(kValue);
87  MockPropertyChangeObserver observer;
88  EXPECT_CALL(observer,
89              OnPropertyChanged(
90                  flimflam::kCellularAllowRoamingProperty,
91                  ValueEq(ByRef(value)))).Times(1);
92
93  // Add the observer
94  client_->AddPropertyChangedObserver(
95      dbus::ObjectPath(kExampleDevicePath),
96      &observer);
97
98  // Run the signal callback.
99  SendPropertyChangedSignal(&signal);
100
101  // Remove the observer.
102  client_->RemovePropertyChangedObserver(
103      dbus::ObjectPath(kExampleDevicePath),
104      &observer);
105
106  EXPECT_CALL(observer,
107              OnPropertyChanged(
108                  flimflam::kCellularAllowRoamingProperty,
109                  ValueEq(ByRef(value)))).Times(0);
110
111  // Run the signal callback again and make sure the observer isn't called.
112  SendPropertyChangedSignal(&signal);
113}
114
115TEST_F(ShillDeviceClientTest, GetProperties) {
116  const bool kValue = true;
117  // Create response.
118  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
119  dbus::MessageWriter writer(response.get());
120  dbus::MessageWriter array_writer(NULL);
121  writer.OpenArray("{sv}", &array_writer);
122  dbus::MessageWriter entry_writer(NULL);
123  array_writer.OpenDictEntry(&entry_writer);
124  entry_writer.AppendString(flimflam::kCellularAllowRoamingProperty);
125  entry_writer.AppendVariantOfBool(kValue);
126  array_writer.CloseContainer(&entry_writer);
127  writer.CloseContainer(&array_writer);
128
129  // Set expectations.
130  base::DictionaryValue value;
131  value.SetWithoutPathExpansion(flimflam::kCellularAllowRoamingProperty,
132                                base::Value::CreateBooleanValue(kValue));
133  PrepareForMethodCall(flimflam::kGetPropertiesFunction,
134                       base::Bind(&ExpectNoArgument),
135                       response.get());
136  // Call method.
137  client_->GetProperties(dbus::ObjectPath(kExampleDevicePath),
138                         base::Bind(&ExpectDictionaryValueResult, &value));
139  // Run the message loop.
140  message_loop_.RunUntilIdle();
141}
142
143TEST_F(ShillDeviceClientTest, ProposeScan) {
144  // Create response.
145  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
146
147  // Set expectations.
148  PrepareForMethodCall(flimflam::kProposeScanFunction,
149                       base::Bind(&ExpectNoArgument),
150                       response.get());
151  // Call method.
152  client_->ProposeScan(dbus::ObjectPath(kExampleDevicePath),
153                       base::Bind(&ExpectNoResultValue));
154  // Run the message loop.
155  message_loop_.RunUntilIdle();
156}
157
158TEST_F(ShillDeviceClientTest, SetProperty) {
159  const bool kValue = true;
160  // Create response.
161  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
162
163  // Set expectations.
164  const base::FundamentalValue value(kValue);
165  PrepareForMethodCall(flimflam::kSetPropertyFunction,
166                       base::Bind(&ExpectStringAndValueArguments,
167                                  flimflam::kCellularAllowRoamingProperty,
168                                  &value),
169                       response.get());
170  // Call method.
171  MockClosure mock_closure;
172  MockErrorCallback mock_error_callback;
173  client_->SetProperty(dbus::ObjectPath(kExampleDevicePath),
174                       flimflam::kCellularAllowRoamingProperty,
175                       value,
176                       mock_closure.GetCallback(),
177                       mock_error_callback.GetCallback());
178  EXPECT_CALL(mock_closure, Run()).Times(1);
179  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
180
181  // Run the message loop.
182  message_loop_.RunUntilIdle();
183}
184
185TEST_F(ShillDeviceClientTest, ClearProperty) {
186  // Create response.
187  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
188
189  // Set expectations.
190  PrepareForMethodCall(flimflam::kClearPropertyFunction,
191                       base::Bind(&ExpectStringArgument,
192                                  flimflam::kCellularAllowRoamingProperty),
193                       response.get());
194  // Call method.
195  client_->ClearProperty(dbus::ObjectPath(kExampleDevicePath),
196                         flimflam::kCellularAllowRoamingProperty,
197                         base::Bind(&ExpectNoResultValue));
198  // Run the message loop.
199  message_loop_.RunUntilIdle();
200}
201
202TEST_F(ShillDeviceClientTest, AddIPConfig) {
203  const dbus::ObjectPath expected_result("/result/path");
204  // Create response.
205  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
206  dbus::MessageWriter writer(response.get());
207  writer.AppendObjectPath(expected_result);
208
209  // Set expectations.
210  PrepareForMethodCall(flimflam::kAddIPConfigFunction,
211                       base::Bind(&ExpectStringArgument, flimflam::kTypeDHCP),
212                       response.get());
213  // Call method.
214  client_->AddIPConfig(dbus::ObjectPath(kExampleDevicePath),
215                       flimflam::kTypeDHCP,
216                       base::Bind(&ExpectObjectPathResult, expected_result));
217  // Run the message loop.
218  message_loop_.RunUntilIdle();
219}
220
221TEST_F(ShillDeviceClientTest, RequirePin) {
222  const char kPin[] = "123456";
223  const bool kRequired = true;
224  // Create response.
225  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
226
227  // Set expectations.
228  MockClosure mock_closure;
229  MockErrorCallback mock_error_callback;
230  PrepareForMethodCall(flimflam::kRequirePinFunction,
231                       base::Bind(&ExpectStringAndBoolArguments,
232                                  kPin,
233                                  kRequired),
234                       response.get());
235  EXPECT_CALL(mock_closure, Run()).Times(1);
236  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
237  // Call method.
238  client_->RequirePin(dbus::ObjectPath(kExampleDevicePath),
239                      kPin,
240                      kRequired,
241                      mock_closure.GetCallback(),
242                      mock_error_callback.GetCallback());
243  // Run the message loop.
244  message_loop_.RunUntilIdle();
245}
246
247TEST_F(ShillDeviceClientTest, EnterPin) {
248  const char kPin[] = "123456";
249  // Create response.
250  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
251
252  // Set expectations.
253  MockClosure mock_closure;
254  MockErrorCallback mock_error_callback;
255  PrepareForMethodCall(flimflam::kEnterPinFunction,
256                       base::Bind(&ExpectStringArgument,
257                                  kPin),
258                       response.get());
259  EXPECT_CALL(mock_closure, Run()).Times(1);
260  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
261
262  // Call method.
263  client_->EnterPin(dbus::ObjectPath(kExampleDevicePath),
264                    kPin,
265                    mock_closure.GetCallback(),
266                    mock_error_callback.GetCallback());
267  // Run the message loop.
268  message_loop_.RunUntilIdle();
269}
270
271TEST_F(ShillDeviceClientTest, UnblockPin) {
272  const char kPuk[] = "987654";
273  const char kPin[] = "123456";
274  // Create response.
275  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
276
277  // Set expectations.
278  MockClosure mock_closure;
279  MockErrorCallback mock_error_callback;
280  PrepareForMethodCall(flimflam::kUnblockPinFunction,
281                       base::Bind(&ExpectTwoStringArguments, kPuk, kPin),
282                       response.get());
283  EXPECT_CALL(mock_closure, Run()).Times(1);
284  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
285
286  // Call method.
287  client_->UnblockPin(dbus::ObjectPath(kExampleDevicePath),
288                      kPuk,
289                      kPin,
290                      mock_closure.GetCallback(),
291                      mock_error_callback.GetCallback());
292  // Run the message loop.
293  message_loop_.RunUntilIdle();
294}
295
296TEST_F(ShillDeviceClientTest, ChangePin) {
297  const char kOldPin[] = "123456";
298  const char kNewPin[] = "234567";
299  // Create response.
300  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
301
302  // Set expectations.
303  MockClosure mock_closure;
304  MockErrorCallback mock_error_callback;
305  PrepareForMethodCall(flimflam::kChangePinFunction,
306                       base::Bind(&ExpectTwoStringArguments,
307                                  kOldPin,
308                                  kNewPin),
309                       response.get());
310  EXPECT_CALL(mock_closure, Run()).Times(1);
311  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
312
313  // Call method.
314  client_->ChangePin(dbus::ObjectPath(kExampleDevicePath),
315                     kOldPin,
316                     kNewPin,
317                     mock_closure.GetCallback(),
318                     mock_error_callback.GetCallback());
319  // Run the message loop.
320  message_loop_.RunUntilIdle();
321}
322
323TEST_F(ShillDeviceClientTest, Register) {
324  const char kNetworkId[] = "networkid";
325  // Create response.
326  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
327
328  // Set expectations.
329  MockClosure mock_closure;
330  MockErrorCallback mock_error_callback;
331  PrepareForMethodCall(flimflam::kRegisterFunction,
332                       base::Bind(&ExpectStringArgument, kNetworkId),
333                       response.get());
334  EXPECT_CALL(mock_closure, Run()).Times(1);
335  EXPECT_CALL(mock_error_callback, Run(_, _)).Times(0);
336
337  // Call method.
338  client_->Register(dbus::ObjectPath(kExampleDevicePath),
339                    kNetworkId,
340                    mock_closure.GetCallback(),
341                    mock_error_callback.GetCallback());
342  // Run the message loop.
343  message_loop_.RunUntilIdle();
344}
345
346TEST_F(ShillDeviceClientTest, SetCarrier) {
347  const char kCarrier[] = "carrier";
348  // Create response.
349  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
350
351  // Set expectations.
352  MockClosure mock_closure;
353  MockErrorCallback mock_error_callback;
354  PrepareForMethodCall(shill::kSetCarrierFunction,
355                       base::Bind(&ExpectStringArgument, kCarrier),
356                       response.get());
357  EXPECT_CALL(mock_closure, Run()).Times(1);
358  // Call method.
359  client_->SetCarrier(dbus::ObjectPath(kExampleDevicePath),
360                    kCarrier,
361                    mock_closure.GetCallback(),
362                    mock_error_callback.GetCallback());
363  // Run the message loop.
364  message_loop_.RunUntilIdle();
365}
366
367TEST_F(ShillDeviceClientTest, Reset) {
368  // Create response.
369  scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
370
371  // Set expectations.
372  MockClosure mock_closure;
373  MockErrorCallback mock_error_callback;
374  PrepareForMethodCall(shill::kResetFunction,
375                       base::Bind(&ExpectNoArgument),
376                       response.get());
377  EXPECT_CALL(mock_closure, Run()).Times(1);
378  // Call method.
379  client_->Reset(dbus::ObjectPath(kExampleDevicePath),
380                 mock_closure.GetCallback(),
381                 mock_error_callback.GetCallback());
382  // Run the message loop.
383  message_loop_.RunUntilIdle();
384}
385
386}  // namespace chromeos
387